From 93647fb43c34252e724512fa57fb6d15cbbad2df Mon Sep 17 00:00:00 2001 From: NootNoot0 <161794667+NootNoot0@users.noreply.github.com> Date: Mon, 24 Jun 2024 15:57:59 +0800 Subject: [PATCH 1/3] Add files via upload --- kubeflow/LICENSE | 201 + kubeflow/README.md | 354 + kubeflow/examples/0.helloworld/flows.json | 101 + .../examples/0.helloworld/flows_cred.json | 3 + kubeflow/examples/0.helloworld/helloworld.py | 6 + kubeflow/examples/0.helloworld/package.json | 6 + kubeflow/examples/0.helloworld/settings.js | 498 + .../examples/1.connect-kubeflow/flows.json | 368 + .../1.connect-kubeflow/flows_cred.json | 3 + .../node_modules/nodepipe/LSTM.html | 149 + .../node_modules/nodepipe/LSTM.js | 66 + .../node_modules/nodepipe/LSTM0.js | 147 + .../node_modules/nodepipe/decisionTree0.js | 147 + .../node_modules/nodepipe/decisiontree.html | 149 + .../node_modules/nodepipe/decisiontree.js | 66 + .../node_modules/nodepipe/fl.html | 149 + .../node_modules/nodepipe/fl.js | 66 + .../node_modules/nodepipe/fl0.js | 147 + .../node_modules/nodepipe/mnist.html | 149 + .../node_modules/nodepipe/mnist.js | 66 + .../node_modules/nodepipe/mnist0.js | 147 + .../node_modules/nodepipe/package.json | 30 + .../examples/1.connect-kubeflow/package.json | 6 + .../examples/1.connect-kubeflow/py/LSTM.py | 132 + .../examples/1.connect-kubeflow/py/README.md | 18 + .../py/__pycache__/kfp_login.cpython-38.pyc | Bin 0 -> 1992 bytes .../py/__pycache__/kfp_login.cpython-39.pyc | Bin 0 -> 2016 bytes .../__pycache__/kfp_namespace.cpython-38.pyc | Bin 0 -> 944 bytes .../__pycache__/kfp_namespace.cpython-39.pyc | Bin 0 -> 942 bytes .../py/api_examples/create_experiment.py | 59 + .../py/api_examples/create_run.py | 58 + .../py/api_examples/delete_experiment.py | 51 + .../py/api_examples/delete_pipeline.py | 50 + .../py/api_examples/delete_run.py | 50 + .../py/api_examples/get_run.py | 64 + .../py/api_examples/kfp_login.py | 93 + .../py/api_examples/kfp_namespace.py | 19 + .../py/api_examples/list_experiments.py | 44 + .../py/api_examples/list_pipelines.py | 43 + .../py/api_examples/upload_pipeline.py | 52 + .../1.connect-kubeflow/py/decisionTree.py | 132 + kubeflow/examples/1.connect-kubeflow/py/fl.py | 132 + .../1.connect-kubeflow/py/helloworld.py | 6 + .../examples/1.connect-kubeflow/py/install.py | 23 + .../1.connect-kubeflow/py/kfp_example.py | 44 + .../1.connect-kubeflow/py/kfp_login.py | 93 + .../1.connect-kubeflow/py/kfp_namespace.py | 19 + .../examples/1.connect-kubeflow/py/mnist.py | 132 + .../py/pipelines/LSTM_pipeline.yaml | 651 + .../py/pipelines/fl_pipeline.yaml | 639 + .../py/pipelines/mnist_pipeline.yaml | 211 + .../py/pipelines/only_decision_tree.yaml | 131 + .../py/pipelines/three-pipeline.yaml | 229 + .../1.connect-kubeflow/py/requirements.txt | 2 + .../examples/1.connect-kubeflow/settings.js | 498 + kubeflow/examples/Dockerfile | 20 + kubeflow/examples/README.md | 40 + kubeflow/examples/build.sh | 3 + kubeflow/examples/docker-compose.yaml | 33 + kubeflow/examples/package-lock.json | 10782 ++++++++++++++++ kubeflow/examples/package.json | 127 + kubeflow/examples/run.sh | 15 + kubeflow/examples/scripts/entrypoint.sh | 14 + 63 files changed, 17733 insertions(+) create mode 100644 kubeflow/LICENSE create mode 100644 kubeflow/README.md create mode 100644 kubeflow/examples/0.helloworld/flows.json create mode 100644 kubeflow/examples/0.helloworld/flows_cred.json create mode 100644 kubeflow/examples/0.helloworld/helloworld.py create mode 100644 kubeflow/examples/0.helloworld/package.json create mode 100644 kubeflow/examples/0.helloworld/settings.js create mode 100644 kubeflow/examples/1.connect-kubeflow/flows.json create mode 100644 kubeflow/examples/1.connect-kubeflow/flows_cred.json create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.html create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js create mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json create mode 100644 kubeflow/examples/1.connect-kubeflow/package.json create mode 100644 kubeflow/examples/1.connect-kubeflow/py/LSTM.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/README.md create mode 100644 kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc create mode 100644 kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc create mode 100644 kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc create mode 100644 kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/decisionTree.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/fl.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/helloworld.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/install.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/kfp_example.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/kfp_login.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/mnist.py create mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml create mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml create mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml create mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml create mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml create mode 100644 kubeflow/examples/1.connect-kubeflow/py/requirements.txt create mode 100644 kubeflow/examples/1.connect-kubeflow/settings.js create mode 100644 kubeflow/examples/Dockerfile create mode 100644 kubeflow/examples/README.md create mode 100644 kubeflow/examples/build.sh create mode 100644 kubeflow/examples/docker-compose.yaml create mode 100644 kubeflow/examples/package-lock.json create mode 100644 kubeflow/examples/package.json create mode 100644 kubeflow/examples/run.sh create mode 100644 kubeflow/examples/scripts/entrypoint.sh diff --git a/kubeflow/LICENSE b/kubeflow/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/kubeflow/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/kubeflow/README.md b/kubeflow/README.md new file mode 100644 index 000000000..ecdb567e3 --- /dev/null +++ b/kubeflow/README.md @@ -0,0 +1,354 @@ +# Kube-node-red(en) +[![hackmd-github-sync-badge](https://hackmd.io/cocSOGQMR-qzo7DHdwgRsQ/badge)](https://hackmd.io/cocSOGQMR-qzo7DHdwgRsQ) + +Kube-node-red is aiming to integrate Kubeflow/Kubebeters with node-red, leveraging node-red's low-code modules, and using Kubeflow resources (e.g. Kubeflow pipeline, Kserve) to enhance its AI/ML ability. +## Table of Contents + + +- [Installation](#installation) + * [Prerequisites](#Prerequisites) + * [Building](#Building) + * [Install dependencies](#Install-dependencies) +- [Using our nodes](#Using-our-nodes) +- [Test python files to interact with kubeflow](#Test-python-files-to-interact-with-kubeflow) +- [possible problems and solution](#possible-problems-and-solution) +- [Modify your own custom nodes/pipeline](#Modify-your-own-custom-nodes/pipeline) + * [Kubeflow part](#Kubeflow-part) + * [Node-red part](#Node-red-part) +- [Architecture](#Architecture) +- [Demo](#Demo) +- [Reference](#Reference) + + + +# Installation +## Prerequisites +- `Kubeflow` +As this project focused on the node-red integration with Kubeflow, one running Kubeflow instance should be ready on a publicly available network. +(If you need to provision your own Kubeflow instance, you could refer to our [mulitkf](https://github.com/footprintai/multikf) project to allocate one instance for developing.) +- [`WSL`](https://learn.microsoft.com/en-us/windows/wsl/install) If you are Windows OS. +- [`Docker`](https://www.docker.com) + +## Building + +We organized some examples under examples folder, and make sensitive information pass via environment variables. Please refer the following example to launch an individual example: + +1. In terminal (If you on Windows system, please use WSL) +``` +$ git clone https://github.com/NightLightTw/kube-nodered.git +``` +2. Enter target folder +``` +cd kube-nodered/examples +``` +3. Enter account information and start +``` +KUBEFLOW_HOST= \ +KUBEFLOW_USERNAME= \ +KUBEFLOW_PASSWORD= \ +./run.sh +``` +> **Info:** Here please use 1.connect-kubeflow + +## Install dependencies + +1. Then you can go to UI, check it out: http://127.0.0.1:1880/ +![](https://hackmd.io/_uploads/HJ8Rbmdya.png) + +2. Click the “install dependency” button to install dependency items such as specific python libraries and wait for its completion +![](https://hackmd.io/_uploads/rygsMmuy6.png) + +3. Click the “list experiments” button to test the environment work! +![](https://hackmd.io/_uploads/HyXxfX_kp.png) + +## Using our nodes +Switch to the "three-pipeline" flow and press the button to trigger the pipeline process + +![](https://hackmd.io/_uploads/Hkr4mXdk6.png) + +On kubeflow: +![](https://hackmd.io/_uploads/H1_hEX_JT.png) + + + +> **Info:** If the environment variable does not work, please fill in the account password directly in the python file + + +## Test python files to interact with kubeflow +``` +# Open another terminal and check docker status +docker ps +#enter container +docker exec -it bash +#enter document folder +cd /data/1.connect-kubeflow/py/api_examples +#execute function +python3 +``` + +You can test the file in api_example +> **Info:** Some of these files require a custom name, description, or assigned id in + +## Possible problems and solution +Q1: MissingSchema Invalid URL '' + +A1: This problem means that the login information is not accessed correctly, which may be caused by the environment variable not being read. +You can directly override the login information of the specified file + +ex:![](https://hackmd.io/_uploads/ryx59rejBh.jpg) + +Change to your own login information +``` +host = "https://example@test.com" +username = "test01" +password = "123456" +``` + +# Modify your own custom nodes/pipeline +![implementation architecture](https://hackmd.io/_uploads/H1ZLgUsH2.png) + +## Kubeflow part +### Custom make pipeline’s yaml file +Please refer to [Kubeflow implementation:add Random Forest algorithm](https://hackmd.io/@Nhi7So-lTz2m5R6pHyCLcA/Sk1eZFTbh) + +### Take changing randomForest.py as an example + +Modify using your own yaml file path +> **Info:** Line 66: uploadfile='pipelines/only_randomforest.yaml' + +> **Info:** Line 122~129 use json parser for filtering different outputs from get_run() + +```python= +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for only_randomforest." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/only_randomforest.yaml' + name='pipeline-' + random_suffix() + description="This is a only_randomForest pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'run_only_randomForest' + random_suffix() + description = "This is a only_randomForest run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'random-forest-classifier-Accuracy': #change parameter + output_value = parameter['value'] + + if output_value is not None: + print(f"Random Forest Classifier Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) +``` + +## Node-red part +**Package nodered pyshell node** + +**A node mainly consists of two files** +* **Javascript file(.js)** +define what the node does +* **HTML file(.html)** +Define the properties of the node and the windows and help messages in the Node-RED editor + +**When finally package into npm module, will need package.json** + + +### **package.json** +A standard file for describing the content of node.js modules + +A standard package.json can be generated using npm init. This command will ask a series of questions to find a reasonable default value. When asked for the name of the module name: enter the example name node-red-contrib- + +When it is established, you need to manually add the node-red attribute +*p.s. Where the example files need to be changed * + + + +```json= +{ + "name": "node-red-contrib-pythonshell-custom", + ... + "node-red": { + "nodes": { + "decisionTree": "decisiontree.js", + "randomForest": "randomforest.js", + "logisticRegression": "logisticregression.js" + "":"" + } + }, + ... +} + +``` +### **HTML** +```javascript= + + + + + + + \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js new file mode 100644 index 000000000..d16c5fe18 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js @@ -0,0 +1,66 @@ +/** + * Copyright 2014 Sense Tecnic Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var httpclient; +var PythonshellNode = require('./LSTM0'); + +module.exports = function(RED) { + "use strict"; + + function PythonshellInNode(n) { + RED.nodes.createNode(this,n); + + var node = this; + node.config = n; // copy config to the backend so that down bellow we can have a reference + + var pyNode = new PythonshellNode(n); + + pyNode.setStatusCallback(node.status.bind(node)) + + node.on("input",function(msg) { + pyNode.onInput(msg, function(result){ + node.send(result); + }, function(err){ + node.error(err); + }); + }); + + node.on('close', ()=>pyNode.onClose()); + } + + RED.nodes.registerType("LSTM", PythonshellInNode); + + RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + if (node.config.continuous){// see above comment + node.receive({payload: 'pythonshell@close'}) + } else { + node.receive(); + } + res.sendStatus(200); + } catch(err) { + res.sendStatus(500); + node.error(RED._("pythonshell.failed",{error:err.toString()})); + } + } else { + res.sendStatus(404); + } + }); + +} diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js new file mode 100644 index 000000000..86c0742f4 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js @@ -0,0 +1,147 @@ +var fs = require("fs"); + +function PythonshellInNode(config) { + if (!config.pyfile){ + throw 'pyfile not present'; + } + this.pythonExec = config.python3 ? "python3" : "python"; + this.pyfile = '/data/1.connect-kubeflow/py/LSTM.py'; + this.virtualenv = config.virtualenv; + + if (!fs.existsSync(this.pyfile)) { + throw 'pyfile not exist'; + } + + if (this.virtualenv && !fs.existsSync(this.virtualenv)){ + throw 'configured virtualenv not exist, consider remove or change'; + } + + this.stdInData = config.stdInData; + this.continuous = this.stdInData ? true : config.continuous; + this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); + this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); + this.spawn = require('child_process').spawn; + this.onStatus = ()=>{} +} + +PythonshellInNode.prototype.onInput = function(msg, out, err) { + payload = msg.payload || ''; + if (typeof payload === 'object'){ + payload = JSON.stringify(payload); + } else if (typeof payload !== 'string'){ + payload = payload.toString(); + } + + if (payload === 'pythonshell@close'){ + if (this.py != null){ + this.onClose() + return + } else { + // trigger new execution + payload = '' + } + } + + if (this.continuous && !this.stdInData && this.py != null){ + this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) + return + } + + var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec + + if (this.stdInData){ + if (!this.py){ + this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { + cwd: this.pydir, + detached: true + }); + this.firstExecution = true + } else { + this.firstExecution = false + } + } else { + this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { + cwd: this.pydir + }); + } + + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + + // subsequence message, no need to setup callbacks + if (this.stdInData && !this.firstExecution){ + this.py.stdin.write(payload + '\n') + return + } + + var py = this.py; + var dataString = ''; + var errString = ''; + + py.stdout.on('data', data => { + clearTimeout(this.standbyTimer) + + this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) + + let dataStr = data.toString(); + + dataString += dataStr; + + if (dataString.endsWith("\n")){ + if (this.continuous){ + msg.payload = dataString; + out(msg); + dataString = '' + } + } + + this.standbyTimer = setTimeout(()=>{ + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + }, 2000) + + }); + + py.stderr.on('data', data => { + errString += String(data);// just a different way to do it + this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) + }); + + py.stderr.on('error', console.log) + py.stdout.on('error', console.log) + py.stdin.on('error', console.log) + py.on('error', console.log) + + py.on('close', code =>{ + if (code){ + err('exit code: ' + code + ', ' + errString); + this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) + } else if (!this.continuous){ + msg.payload = dataString.trim(); + out(msg); + this.onStatus({fill:"green",shape:"dot",text:"Done"}) + } else { + this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) + } + this.py = null + setTimeout(()=>{ + this.onStatus({}) + }, 2000) + }); + + if (this.stdInData){ + py.stdin.write(payload + '\n') + } +}; + +PythonshellInNode.prototype.onClose = function() { + if (this.py){ + this.py.kill() + this.py = null + } +}; + +PythonshellInNode.prototype.setStatusCallback = function(callback) { + this.onStatus = callback +}; + + +module.exports = PythonshellInNode \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js new file mode 100644 index 000000000..7a8f3a690 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js @@ -0,0 +1,147 @@ +var fs = require("fs"); + +function PythonshellInNode(config) { + if (!config.pyfile){ + throw 'pyfile not present'; + } + this.pythonExec = config.python3 ? "python3" : "python"; + this.pyfile = "/data/1.connect-kubeflow/py/decisionTree.py"; + this.virtualenv = config.virtualenv; + + if (!fs.existsSync(this.pyfile)) { + throw 'pyfile not exist'; + } + + if (this.virtualenv && !fs.existsSync(this.virtualenv)){ + throw 'configured virtualenv not exist, consider remove or change'; + } + + this.stdInData = config.stdInData; + this.continuous = this.stdInData ? true : config.continuous; + this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); + this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); + this.spawn = require('child_process').spawn; + this.onStatus = ()=>{} +} + +PythonshellInNode.prototype.onInput = function(msg, out, err) { + payload = msg.payload || ''; + if (typeof payload === 'object'){ + payload = JSON.stringify(payload); + } else if (typeof payload !== 'string'){ + payload = payload.toString(); + } + + if (payload === 'pythonshell@close'){ + if (this.py != null){ + this.onClose() + return + } else { + // trigger new execution + payload = '' + } + } + + if (this.continuous && !this.stdInData && this.py != null){ + this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) + return + } + + var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec + + if (this.stdInData){ + if (!this.py){ + this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { + cwd: this.pydir, + detached: true + }); + this.firstExecution = true + } else { + this.firstExecution = false + } + } else { + this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { + cwd: this.pydir + }); + } + + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + + // subsequence message, no need to setup callbacks + if (this.stdInData && !this.firstExecution){ + this.py.stdin.write(payload + '\n') + return + } + + var py = this.py; + var dataString = ''; + var errString = ''; + + py.stdout.on('data', data => { + clearTimeout(this.standbyTimer) + + this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) + + let dataStr = data.toString(); + + dataString += dataStr; + + if (dataString.endsWith("\n")){ + if (this.continuous){ + msg.payload = dataString; + out(msg); + dataString = '' + } + } + + this.standbyTimer = setTimeout(()=>{ + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + }, 2000) + + }); + + py.stderr.on('data', data => { + errString += String(data);// just a different way to do it + this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) + }); + + py.stderr.on('error', console.log) + py.stdout.on('error', console.log) + py.stdin.on('error', console.log) + py.on('error', console.log) + + py.on('close', code =>{ + if (code){ + err('exit code: ' + code + ', ' + errString); + this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) + } else if (!this.continuous){ + msg.payload = dataString.trim(); + out(msg); + this.onStatus({fill:"green",shape:"dot",text:"Done"}) + } else { + this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) + } + this.py = null + setTimeout(()=>{ + this.onStatus({}) + }, 2000) + }); + + if (this.stdInData){ + py.stdin.write(payload + '\n') + } +}; + +PythonshellInNode.prototype.onClose = function() { + if (this.py){ + this.py.kill() + this.py = null + } +}; + +PythonshellInNode.prototype.setStatusCallback = function(callback) { + this.onStatus = callback +}; + + +module.exports = PythonshellInNode \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html new file mode 100644 index 000000000..2045d7745 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html @@ -0,0 +1,149 @@ +f + + + + + + + \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js new file mode 100644 index 000000000..1727299e0 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js @@ -0,0 +1,66 @@ +/** + * Copyright 2014 Sense Tecnic Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var httpclient; +var PythonshellNode = require('./decisionTree0'); + +module.exports = function(RED) { + "use strict"; + + function PythonshellInNode(n) { + RED.nodes.createNode(this,n); + + var node = this; + node.config = n; // copy config to the backend so that down bellow we can have a reference + + var pyNode = new PythonshellNode(n); + + pyNode.setStatusCallback(node.status.bind(node)) + + node.on("input",function(msg) { + pyNode.onInput(msg, function(result){ + node.send(result); + }, function(err){ + node.error(err); + }); + }); + + node.on('close', ()=>pyNode.onClose()); + } + + RED.nodes.registerType("decisionTree", PythonshellInNode); + + RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + if (node.config.continuous){// see above comment + node.receive({payload: 'pythonshell@close'}) + } else { + node.receive(); + } + res.sendStatus(200); + } catch(err) { + res.sendStatus(500); + node.error(RED._("pythonshell.failed",{error:err.toString()})); + } + } else { + res.sendStatus(404); + } + }); + +} diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html new file mode 100644 index 000000000..35f46a295 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html @@ -0,0 +1,149 @@ +f + + + + + + + \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js new file mode 100644 index 000000000..edabfa19e --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js @@ -0,0 +1,66 @@ +/** + * Copyright 2014 Sense Tecnic Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var httpclient; +var PythonshellNode = require('./fl0'); + +module.exports = function(RED) { + "use strict"; + + function PythonshellInNode(n) { + RED.nodes.createNode(this,n); + + var node = this; + node.config = n; // copy config to the backend so that down bellow we can have a reference + + var pyNode = new PythonshellNode(n); + + pyNode.setStatusCallback(node.status.bind(node)) + + node.on("input",function(msg) { + pyNode.onInput(msg, function(result){ + node.send(result); + }, function(err){ + node.error(err); + }); + }); + + node.on('close', ()=>pyNode.onClose()); + } + + RED.nodes.registerType("fl", PythonshellInNode); + + RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + if (node.config.continuous){// see above comment + node.receive({payload: 'pythonshell@close'}) + } else { + node.receive(); + } + res.sendStatus(200); + } catch(err) { + res.sendStatus(500); + node.error(RED._("pythonshell.failed",{error:err.toString()})); + } + } else { + res.sendStatus(404); + } + }); + +} diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js new file mode 100644 index 000000000..ee8b3f222 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js @@ -0,0 +1,147 @@ +var fs = require("fs"); + +function PythonshellInNode(config) { + if (!config.pyfile){ + throw 'pyfile not present'; + } + this.pythonExec = config.python3 ? "python3" : "python"; + this.pyfile = "/data/1.connect-kubeflow/py/fl.py"; + this.virtualenv = config.virtualenv; + + if (!fs.existsSync(this.pyfile)) { + throw 'pyfile not exist'; + } + + if (this.virtualenv && !fs.existsSync(this.virtualenv)){ + throw 'configured virtualenv not exist, consider remove or change'; + } + + this.stdInData = config.stdInData; + this.continuous = this.stdInData ? true : config.continuous; + this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); + this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); + this.spawn = require('child_process').spawn; + this.onStatus = ()=>{} +} + +PythonshellInNode.prototype.onInput = function(msg, out, err) { + payload = msg.payload || ''; + if (typeof payload === 'object'){ + payload = JSON.stringify(payload); + } else if (typeof payload !== 'string'){ + payload = payload.toString(); + } + + if (payload === 'pythonshell@close'){ + if (this.py != null){ + this.onClose() + return + } else { + // trigger new execution + payload = '' + } + } + + if (this.continuous && !this.stdInData && this.py != null){ + this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) + return + } + + var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec + + if (this.stdInData){ + if (!this.py){ + this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { + cwd: this.pydir, + detached: true + }); + this.firstExecution = true + } else { + this.firstExecution = false + } + } else { + this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { + cwd: this.pydir + }); + } + + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + + // subsequence message, no need to setup callbacks + if (this.stdInData && !this.firstExecution){ + this.py.stdin.write(payload + '\n') + return + } + + var py = this.py; + var dataString = ''; + var errString = ''; + + py.stdout.on('data', data => { + clearTimeout(this.standbyTimer) + + this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) + + let dataStr = data.toString(); + + dataString += dataStr; + + if (dataString.endsWith("\n")){ + if (this.continuous){ + msg.payload = dataString; + out(msg); + dataString = '' + } + } + + this.standbyTimer = setTimeout(()=>{ + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + }, 2000) + + }); + + py.stderr.on('data', data => { + errString += String(data);// just a different way to do it + this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) + }); + + py.stderr.on('error', console.log) + py.stdout.on('error', console.log) + py.stdin.on('error', console.log) + py.on('error', console.log) + + py.on('close', code =>{ + if (code){ + err('exit code: ' + code + ', ' + errString); + this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) + } else if (!this.continuous){ + msg.payload = dataString.trim(); + out(msg); + this.onStatus({fill:"green",shape:"dot",text:"Done"}) + } else { + this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) + } + this.py = null + setTimeout(()=>{ + this.onStatus({}) + }, 2000) + }); + + if (this.stdInData){ + py.stdin.write(payload + '\n') + } +}; + +PythonshellInNode.prototype.onClose = function() { + if (this.py){ + this.py.kill() + this.py = null + } +}; + +PythonshellInNode.prototype.setStatusCallback = function(callback) { + this.onStatus = callback +}; + + +module.exports = PythonshellInNode \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html new file mode 100644 index 000000000..322e0e99d --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html @@ -0,0 +1,149 @@ +f + + + + + + + \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js new file mode 100644 index 000000000..3c3e04c13 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js @@ -0,0 +1,66 @@ +/** + * Copyright 2014 Sense Tecnic Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var httpclient; +var PythonshellNode = require('./mnist0'); + +module.exports = function(RED) { + "use strict"; + + function PythonshellInNode(n) { + RED.nodes.createNode(this,n); + + var node = this; + node.config = n; // copy config to the backend so that down bellow we can have a reference + + var pyNode = new PythonshellNode(n); + + pyNode.setStatusCallback(node.status.bind(node)) + + node.on("input",function(msg) { + pyNode.onInput(msg, function(result){ + node.send(result); + }, function(err){ + node.error(err); + }); + }); + + node.on('close', ()=>pyNode.onClose()); + } + + RED.nodes.registerType("mnist", PythonshellInNode); + + RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + if (node.config.continuous){// see above comment + node.receive({payload: 'pythonshell@close'}) + } else { + node.receive(); + } + res.sendStatus(200); + } catch(err) { + res.sendStatus(500); + node.error(RED._("pythonshell.failed",{error:err.toString()})); + } + } else { + res.sendStatus(404); + } + }); + +} diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js new file mode 100644 index 000000000..58ebc34a3 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js @@ -0,0 +1,147 @@ +var fs = require("fs"); + +function PythonshellInNode(config) { + if (!config.pyfile){ + throw 'pyfile not present'; + } + this.pythonExec = config.python3 ? "python3" : "python"; + this.pyfile = "/data/1.connect-kubeflow/py/mnist.py"; + this.virtualenv = config.virtualenv; + + if (!fs.existsSync(this.pyfile)) { + throw 'pyfile not exist'; + } + + if (this.virtualenv && !fs.existsSync(this.virtualenv)){ + throw 'configured virtualenv not exist, consider remove or change'; + } + + this.stdInData = config.stdInData; + this.continuous = this.stdInData ? true : config.continuous; + this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); + this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); + this.spawn = require('child_process').spawn; + this.onStatus = ()=>{} +} + +PythonshellInNode.prototype.onInput = function(msg, out, err) { + payload = msg.payload || ''; + if (typeof payload === 'object'){ + payload = JSON.stringify(payload); + } else if (typeof payload !== 'string'){ + payload = payload.toString(); + } + + if (payload === 'pythonshell@close'){ + if (this.py != null){ + this.onClose() + return + } else { + // trigger new execution + payload = '' + } + } + + if (this.continuous && !this.stdInData && this.py != null){ + this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) + return + } + + var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec + + if (this.stdInData){ + if (!this.py){ + this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { + cwd: this.pydir, + detached: true + }); + this.firstExecution = true + } else { + this.firstExecution = false + } + } else { + this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { + cwd: this.pydir + }); + } + + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + + // subsequence message, no need to setup callbacks + if (this.stdInData && !this.firstExecution){ + this.py.stdin.write(payload + '\n') + return + } + + var py = this.py; + var dataString = ''; + var errString = ''; + + py.stdout.on('data', data => { + clearTimeout(this.standbyTimer) + + this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) + + let dataStr = data.toString(); + + dataString += dataStr; + + if (dataString.endsWith("\n")){ + if (this.continuous){ + msg.payload = dataString; + out(msg); + dataString = '' + } + } + + this.standbyTimer = setTimeout(()=>{ + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + }, 2000) + + }); + + py.stderr.on('data', data => { + errString += String(data);// just a different way to do it + this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) + }); + + py.stderr.on('error', console.log) + py.stdout.on('error', console.log) + py.stdin.on('error', console.log) + py.on('error', console.log) + + py.on('close', code =>{ + if (code){ + err('exit code: ' + code + ', ' + errString); + this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) + } else if (!this.continuous){ + msg.payload = dataString.trim(); + out(msg); + this.onStatus({fill:"green",shape:"dot",text:"Done"}) + } else { + this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) + } + this.py = null + setTimeout(()=>{ + this.onStatus({}) + }, 2000) + }); + + if (this.stdInData){ + py.stdin.write(payload + '\n') + } +}; + +PythonshellInNode.prototype.onClose = function() { + if (this.py){ + this.py.kill() + this.py = null + } +}; + +PythonshellInNode.prototype.setStatusCallback = function(callback) { + this.onStatus = callback +}; + + +module.exports = PythonshellInNode \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json new file mode 100644 index 000000000..fcf46cd21 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json @@ -0,0 +1,30 @@ +{ + "name": "node-red-contrib-pythonshell-custom", + "version": "1.0.0", + "description": "modified version of node-red-contrib-pythonshell with additional features", + "scripts": { + "test": "./node_modules/mocha/bin/mocha" + }, + "keywords": [ + "distributed", + "python", + "node", + "node-red" + ], + "author": "WuChunYen", + "license": "ISC", + "dependencies": {}, + "node-red": { + "nodes": { + "decisionTree": "decisiontree.js", + "randomForest": "randomforest.js", + "logisticRegression": "logisticregression.js", + "fl": "fl.js", + "mnist": "mnist.js", + "LSTM": "LSTM.js" + } + }, + "devDependencies": { + "mocha": "^5.0.4" + } +} diff --git a/kubeflow/examples/1.connect-kubeflow/package.json b/kubeflow/examples/1.connect-kubeflow/package.json new file mode 100644 index 000000000..b788fd491 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/package.json @@ -0,0 +1,6 @@ +{ + "name": "node-red-project", + "description": "A Node-RED Project", + "version": "0.0.1", + "private": true +} \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/LSTM.py b/kubeflow/examples/1.connect-kubeflow/py/LSTM.py new file mode 100644 index 000000000..0eb2cb76a --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/LSTM.py @@ -0,0 +1,132 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "https://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for LSTM." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/LSTM_pipeline.yaml' + name='pipeline-' + random_suffix() + description="This is a LSTM pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'LSTM' + random_suffix() + description = "This is a LSTM run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'random-forest-classifier-Accuracy': #change parameter + output_value = parameter['value'] + + if output_value is not None: + print(f"Random Forest Classifier Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) diff --git a/kubeflow/examples/1.connect-kubeflow/py/README.md b/kubeflow/examples/1.connect-kubeflow/py/README.md new file mode 100644 index 000000000..06bb167e4 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/README.md @@ -0,0 +1,18 @@ +## How to use +``` +KUBEFLOW_HOST= \ +KUBEFLOW_USERNAME= \ +KUBEFLOW_PASSWORD= \ +python3 +``` +## three pipelines +流程架構: +create_experiment -> upload_pipeline -> create_run -> get_run -> filter -> result +### decisionTree.py +功能:以乳癌資料集訓練decisionTree模型並回傳準確率 + +### logisticRegression.py +功能:以乳癌資料集訓練logisticRegression模型並回傳準確率 + +### randomForest.py +功能:以乳癌資料集訓練randomForest模型並回傳準確率 diff --git a/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc b/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..193a91af9ab988978f2373b5b3ad1d940277f916 GIT binary patch literal 1992 zcmah}&2JM&6rb5IZ=AIg0;F(h=YRx`iqlH%#dQ(1Q2G(2Aqh$qR5|ONak9>OXPKEL z#Bwf$V^QguR7%uS@BJfs?0K*4g@1txrEg|!6rfUPwe#`jz2Cg=yR}*s!MJn%9{aJ5 z&|ms+dbn`74!`^eCWQUXVas24K=*yAc>Y6 zxbSn4$SjFf!zpao13@y8h67gkSt#Wm7qsvMQ@KbZTT6{c1y-%*=kUu17@-j;GXAVX z_rO-@2p^-T_@~taXXNxPxVNeE#5!+9^oG_P~4GC z{Weniw(x`-a(15ZsIRcSEt`qRgj z_#M^&C^Z_;nxWaW{$#>6Gv@kp(I0iDjaQTmzD*-+lp`zaRwYnmIbH?#)~K$y{J z7tsihEPCe90;IVo_JMoaESfq@3N+Qm8W7agl8#h*$zgoWCB0Nn>$t|fu6-O)M43S#~YisG|jTPAD z@OTQ>zye62U<95OKmuu*XBiiYQG=}2Hsi`3Bb4>RJW;P!P%D>lx=r4G4GipZwPUbZ z8g>&!kY%0dwi2&8h0e3N%sFX4M&lz6~|_QLxlPNO8J8a5ML@rWm{$&ItWWgPVO z!(5QDm6JL-Ej_82|CgR{meOT?wT$OpMIcUlTnvm44cBtR-3(YtGajd^qiZ#QSjK`y z<*7#5!%o7tS*Uh~GbORP z0CZ6AlJG&KVHK`93f<4(YwM8GEi$w|A(7T`GA!8W$JXGN@4~bVUF-Y#13bcg=spzcw2z?z z?Vqjt4%8NYfj`xXnRe*Hi#da%)%>8q(Qinc2ZR?_7PZ=oA2uVNrVxs&yW^x=%=Q;| zds!KgX0~5c+es`{#0S~6ds+bpCJ!3faABLN4qU~&qn!v*GbPw;8!yUhu$c%7-Etdq zg)i9soJl2%%38@?*nm<@m!X3=Q&t44IXG{?ZVADK(9OHB6P6a09f0FvUub_6mSBY^ zStz0%QPTt;k|ImOh!wWXyM+h1I@z3zOI0|1$iAXd=8X$uN03r8@S zZO%?&q*JrQyM5!la+=qV&i}U$behRkm{85acLTd_ zIktGLfte2iU3$)f55|Eg2qzwBht#$B)QQdD3IL#AwO{bdlVDfQb`S!olK{pft literal 0 HcmV?d00001 diff --git a/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc b/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37989316f586bdf924c9c0c085096deb6c4817a1 GIT binary patch literal 2016 zcmah~&u<(x6t-tPvzyKCCQaKwFUW^V?H0OeB~HsywUAJLR3S8hid3+j9eb16%#NqF zr)i>zgh-DR%DF{Kj{F1s4V*d76)rvZR)oT{XSYgQBs>~>{QTbM=l8wm2^x(Wg7(GL z+x&+nLVudc@#ewgD!l4l=on%+M(bvDVmxxz9bC%Xb(a(Sc+7o57-8N6vhFjyidz0t zutdu(TvRg|t2B;uixe(=gFtba1S4Kl(?F?hAz9%|t}~g0uCW@o3XD~FKZIBPh!M)c zk@4d^@%CJe4)7s*gn#;WkK|bDF=CY*Jx0Hfef&KJ ziI=;q+C|!|R`xNQ+Hz#hY9O8NqTIcO9N3K@g7#gERsp$O(N$x22JPcLUr!y>SUvZL z(}#}y4aPc18m!J5R_3zi!->|+SnH46KWH8TKAY{Lc-sQsx^{EeZ za4S<$vO!7{ss(NdvvPJ5vhV7eEf~ot5T7X*q>wr_$VWFe5C`ft)sIOE-)j4Z%B;NI|UV zHit9<#`-|^4v=^+h$BWX(q%y>XQ06V3V^PBzPbh}-J!eAdo(mYPMQNBX0ugz)mzYQ zz-{);{2tEn5N;&~)jPycm+sHbT>`a*pX2w9WA>W#V8@KZ)M;NTaQG{drvc&l`32+l z!sT`-k_4!@xHV3?g>+|OYmkSi2HsF}?qJA@jz>WBlltM~#p%-q< zlcKT-a6;}#6N|!;yzmtdWVk6CMo@)>NaG;ng{!iD;RCKoG?EIX3o?YvD=K9UsaD0p zN&Tc5^xOwEmYSWv;bQT!uvMEs5;-v(qj z1cjlfgKKfrZ^PvQ7l4V4JY(dp(h?Fg3bj=~=D8tXTKB8nkziTOub5O*K6F)FcdG8c DjCnfW literal 0 HcmV?d00001 diff --git a/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc b/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d49512c6312c4543713547c31315654ef7d280c6 GIT binary patch literal 944 zcmZuuO-~y!5cSuFBqRudgvh1Z8;Vqtw#O<(NCmYg)Ry#;s*1L2Cv38@7uyR;w2`X9 zwTGT*RXFya^f&n06MumVolQ#M(2?fZV|&Ik@4c^9%Lwf4?g#OcAoM2>9vXvS7u-Ap z;E3ZGb>=JXV2DXfMzljQ5=>CRIQ>pJ(3EDFlN!3DoL=E6 zvn*qr)zBHn2zFi#WpsYhLe?7;GLlhV_)4Z;<_(tk(va$bE%IU>T_9e{$OZbr&hQt^ z%Y6A9W!`1!3h_z}?Lkc#sCqEj2$HCIs`Rk0Rhl$~JlT$9Pq~$UlXOF+hLO0zFEoah zuX6wbmgdLi`ZvUrwb$+T8{gQ#rp6By7yi~{ear7D?Z4V@`$0d5q_NNaFwefToSIyb zLvZ5*^ihUBZcZ_ffNDU>kZ3k1a>}Ro5NnxT@+{}V^?m)k+Go~B|B?*OSxPH zL~!MHvIT1DNSuiK4AW@EDhy(?1Dm@%S6);!^|B+%IF!6t}vRUsUJ1 zbgdc+3BPL~=$;Y13UA!{f2PTYH5&j3uMmb;a0RadmNCJrw~XpXa04Bz!=g6uf&19JUS8RN5`{sO@%_O$>2 literal 0 HcmV?d00001 diff --git a/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc b/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c29c28cec6281c9c0c84d4df70e3ff04056ed1e GIT binary patch literal 942 zcmZuvO-~y!5cSuFBqRudgvh1Z8;VqtmSdG7q=MQLYD-S3s%X1*!X_JgvAv)~8>uQ> zd+3=~g=7Coe}k_*@fWzz*`x#x9m&t0wP)tdn+>YfG6H+I_d)z52>r>O$Hu_fgJpIA zIN~@)o%xPC7<>|w5$#Zn1QS#+PQO#mxOc%i9>+(hUbulcbXdo()E*~-??<7nQ^$^# zv91!N_PA?=F_Dt4poLAf41vbN3UKmZy@F*v16VY`S0n=>*JMf}G^H8lq=v32r`LGO zEXx>YHFS zBUr`<=%WmM+?-+%0o6d1A<=9u$TxDrfG+JYtzzLkbtZ*&B^iu_NrF)PLUrOua3ZJo5NnxT_k8EV^?m)k+Go~CA(`mrJP$4 zSMDZTFiRbYQ}OWLG+MC=gV^lC;XcZh7x_%R?1(asC4oJ5Y@j0PJd?zcbzY()XKf#E&_l1n8@K+SZt_3VYycpq#ssh4F{+=y4KP@TO>Y9Yf*mK3 k?CX4njvA|HPac(;4PjQV*cvIG#$q?0y~!&TagkKWU&grhzW@LL literal 0 HcmV?d00001 diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py new file mode 100644 index 000000000..8ac8d7321 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py @@ -0,0 +1,59 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="" # str | The ID of the name to be create. + description='' # str | The description experiment. + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + api_response = api_instance.create_experiment(body) + pprint(api_response) + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py new file mode 100644 index 000000000..b02691de7 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py @@ -0,0 +1,58 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from pprint import pprint +from kfp_server_api.rest import ApiException +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.RunServiceApi(api_client) + pipeline_id = '' # str | The ID of the pipeline. + experiment_id = '' # str | The ID of the experiment. + display_name = '' # str | The name of the run to be create. + description = '' # str | The description of run. + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + + try: + # Creates a new run. + api_response = api_instance.create_run(body) + pprint(api_response) + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py new file mode 100644 index 000000000..31d9205c7 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py @@ -0,0 +1,51 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.ExperimentServiceApi(api_client) + experiment_id = '' # str | The ID of the experiment to be deleted. + + try: + # Deletes an experiment without deleting the experiment's runs and recurring runs. + # To avoid unexpected behaviors, delete an experiment's runs and recurring runs before deleting the experiment. + api_response = api_instance.delete_experiment(experiment_id) + pprint(api_response) + except ApiException as e: + print("Exception when calling ExperimentServiceApi->delete_experiment: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py new file mode 100644 index 000000000..c04d595ef --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py @@ -0,0 +1,50 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.PipelineServiceApi(api_client) + id = '' # str | The ID of the pipeline to be deleted. + + try: + # Deletes a pipeline and its pipeline versions. + api_response = api_instance.delete_pipeline(id) + pprint(api_response) + except ApiException as e: + print("Exception when calling PipelineServiceApi->delete_pipeline: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py new file mode 100644 index 000000000..aefc7dca3 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py @@ -0,0 +1,50 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.RunServiceApi(api_client) + id = '' # str | The ID of the run to be deleted. + + try: + # Deletes a run. + api_response = api_instance.delete_run(id) + pprint(api_response) + except ApiException as e: + print("Exception when calling RunServiceApi->delete_run: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py new file mode 100644 index 000000000..f62c56bdc --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py @@ -0,0 +1,64 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces +import json + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.RunServiceApi(api_client) + run_id = '' # str | The ID of the run to be retrieved. + + try: + # Finds a specific run by ID. + api_response = api_instance.get_run(run_id) + output = api_response.pipeline_runtime.workflow_manifest + output = json.loads(output) + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + output_value = None + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'decision-tree-classifier-Accuracy': + output_value = parameter['value'] + break + + if output_value is not None: + print(f"Decision Tree Classifier Accuracy: {output_value}") + else: + print("Parameter not found.") + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py new file mode 100644 index 000000000..7c95abcf0 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py @@ -0,0 +1,93 @@ +import re +from urllib.parse import urlsplit + +import requests + +# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916 +def get_istio_auth_session(url: str, username: str, password: str) -> dict: + """ + Determine if the specified URL is secured by Dex and try to obtain a session cookie. + WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported + (we default default to using `staticPasswords` if both are enabled) + + :param url: Kubeflow server URL, including protocol + :param username: Dex `staticPasswords` or `LDAP` username + :param password: Dex `staticPasswords` or `LDAP` password + :return: auth session information + """ + # define the default return object + auth_session = { + "endpoint_url": url, # KF endpoint URL + "redirect_url": None, # KF redirect URL, if applicable + "dex_login_url": None, # Dex login URL (for POST of credentials) + "is_secured": None, # True if KF endpoint is secured + "session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2" + } + + # use a persistent session (for cookies) + with requests.Session() as s: + + ################ + # Determine if Endpoint is Secured + ################ + resp = s.get(url, allow_redirects=True) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {url}" + ) + + auth_session["redirect_url"] = resp.url + + # if we were NOT redirected, then the endpoint is UNSECURED + if len(resp.history) == 0: + auth_session["is_secured"] = False + return auth_session + else: + auth_session["is_secured"] = True + + ################ + # Get Dex Login URL + ################ + redirect_url_obj = urlsplit(auth_session["redirect_url"]) + + # if we are at `/auth?=xxxx` path, we need to select an auth type + if re.search(r"/auth$", redirect_url_obj.path): + # default to "staticPasswords" auth type + redirect_url_obj = redirect_url_obj._replace( + path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path) + ) + + # if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST) + if re.search(r"/auth/.*/login$", redirect_url_obj.path): + auth_session["dex_login_url"] = redirect_url_obj.geturl() + + # else, we need to be redirected to the actual login page + else: + # this GET should redirect us to the `/auth/xxxx/login` path + resp = s.get(redirect_url_obj.geturl(), allow_redirects=True) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}" + ) + + # set the login url + auth_session["dex_login_url"] = resp.url + + ################ + # Attempt Dex Login + ################ + resp = s.post( + auth_session["dex_login_url"], + data={"login": username, "password": password}, + allow_redirects=True + ) + if len(resp.history) == 0: + raise RuntimeError( + f"Login credentials were probably invalid - " + f"No redirect after POST to: {auth_session['dex_login_url']}" + ) + + # store the session cookies in a "key1=value1; key2=value2" string + auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies]) + + return auth_session \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py new file mode 100644 index 000000000..3c7c0dfdc --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py @@ -0,0 +1,19 @@ +import os +import requests + +from typing import TypedDict + +def retrieve_namespaces(host: str, auth_session: TypedDict) -> str: + workgroup_endpoint = os.path.join(host, "api/workgroup/env-info") + + cookies = {} + cookie_tokens = auth_session["session_cookie"].split("=") + print(cookie_tokens[0]) + cookies[cookie_tokens[0]]=cookie_tokens[1] + resp = requests.get(workgroup_endpoint, cookies=cookies) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}" + ) + return [ns["namespace"] for ns in resp.json()["namespaces"] if + ns["role"]=="owner"] \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py new file mode 100644 index 000000000..2e4729bea --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py @@ -0,0 +1,44 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.ExperimentServiceApi(api_client) + resource_reference_key_type = "NAMESPACE" + resource_reference_key_id = namespaces[0] + list_experiment_response = api_instance.list_experiment(resource_reference_key_type=resource_reference_key_type, resource_reference_key_id=resource_reference_key_id) + for experiment in list_experiment_response.experiments: + pprint(experiment) diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py new file mode 100644 index 000000000..6e2be4b5e --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py @@ -0,0 +1,43 @@ +from __future__ import print_function +import string +import time +import kfp_server_api +import os +import requests +import kfp +import json +from pprint import pprint +from kfp_server_api.rest import ApiException +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + api_instance = kfp_server_api.PipelineServiceApi(api_client) + list_pipeline_response = api_instance.list_pipelines() + for pipelines in list_pipeline_response.pipelines: + print(pipelines) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py new file mode 100644 index 000000000..410cf50aa --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py @@ -0,0 +1,52 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +from kfp_server_api.rest import ApiException + +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='' # The yaml file in your local path. + name='pipeline-' + random_suffix() + description='' # str | The description of pipeline. + try: + api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + print(api_response) + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py b/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py new file mode 100644 index 000000000..16293f1d6 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py @@ -0,0 +1,132 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "http://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for only_decision_tree." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/only_decision_tree.yaml' + name='pipeline-' + random_suffix() + description="This is a only_decision_tree pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'run_only_decision_tree' + random_suffix() + description = "This is a only_decision_tree run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'decision-tree-classifier-Accuracy': + output_value = parameter['value'] + + if output_value is not None: + print(f"Decision Tree Classifier Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) diff --git a/kubeflow/examples/1.connect-kubeflow/py/fl.py b/kubeflow/examples/1.connect-kubeflow/py/fl.py new file mode 100644 index 000000000..6aeb83f9d --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/fl.py @@ -0,0 +1,132 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "https://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for fl." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/fl_pipeline.yaml' + name='pipeline-' + random_suffix() + description="This is a fl pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'fl' + random_suffix() + description = "This is a fl run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'client-last_accuracy': + output_value = parameter['value'] + + if output_value is not None: + print(f"fl Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) diff --git a/kubeflow/examples/1.connect-kubeflow/py/helloworld.py b/kubeflow/examples/1.connect-kubeflow/py/helloworld.py new file mode 100644 index 000000000..97e823fb5 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/helloworld.py @@ -0,0 +1,6 @@ +import sys + +while True: + line = sys.stdin.readline() + print('this is send from python') + print(line) diff --git a/kubeflow/examples/1.connect-kubeflow/py/install.py b/kubeflow/examples/1.connect-kubeflow/py/install.py new file mode 100644 index 000000000..470d38321 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/install.py @@ -0,0 +1,23 @@ +import os +import subprocess + +def python3_version(): + return subprocess.check_call(["python3", "--version"]) + +def which(command): + return subprocess.check_call(["which", command]) + +def pip3_install_requirements(): + return subprocess.check_call(["pip3", "install", "-r", "requirements.txt", + "--user"]) + +def pip3_install_kfp(): + return subprocess.check_call(["pip3", "install", + "git+https://github.com/kubeflow/pipelines.git@1.8.19#subdirectory=backend/api/python_http_client", + "--user"]) + +python3_version() +pip3_install_requirements() +pip3_install_kfp() + +print("done") diff --git a/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py b/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py new file mode 100644 index 000000000..da7ef822f --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py @@ -0,0 +1,44 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +from kfp_server_api.rest import ApiException + +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "http://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.ExperimentServiceApi(api_client) + resource_reference_key_type = "NAMESPACE" + resource_reference_key_id = namespaces[0] + list_experiment_response = api_instance.list_experiment(resource_reference_key_type=resource_reference_key_type, resource_reference_key_id=resource_reference_key_id) + for experiment in list_experiment_response.experiments: + print(experiment) diff --git a/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py b/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py new file mode 100644 index 000000000..7c95abcf0 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py @@ -0,0 +1,93 @@ +import re +from urllib.parse import urlsplit + +import requests + +# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916 +def get_istio_auth_session(url: str, username: str, password: str) -> dict: + """ + Determine if the specified URL is secured by Dex and try to obtain a session cookie. + WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported + (we default default to using `staticPasswords` if both are enabled) + + :param url: Kubeflow server URL, including protocol + :param username: Dex `staticPasswords` or `LDAP` username + :param password: Dex `staticPasswords` or `LDAP` password + :return: auth session information + """ + # define the default return object + auth_session = { + "endpoint_url": url, # KF endpoint URL + "redirect_url": None, # KF redirect URL, if applicable + "dex_login_url": None, # Dex login URL (for POST of credentials) + "is_secured": None, # True if KF endpoint is secured + "session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2" + } + + # use a persistent session (for cookies) + with requests.Session() as s: + + ################ + # Determine if Endpoint is Secured + ################ + resp = s.get(url, allow_redirects=True) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {url}" + ) + + auth_session["redirect_url"] = resp.url + + # if we were NOT redirected, then the endpoint is UNSECURED + if len(resp.history) == 0: + auth_session["is_secured"] = False + return auth_session + else: + auth_session["is_secured"] = True + + ################ + # Get Dex Login URL + ################ + redirect_url_obj = urlsplit(auth_session["redirect_url"]) + + # if we are at `/auth?=xxxx` path, we need to select an auth type + if re.search(r"/auth$", redirect_url_obj.path): + # default to "staticPasswords" auth type + redirect_url_obj = redirect_url_obj._replace( + path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path) + ) + + # if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST) + if re.search(r"/auth/.*/login$", redirect_url_obj.path): + auth_session["dex_login_url"] = redirect_url_obj.geturl() + + # else, we need to be redirected to the actual login page + else: + # this GET should redirect us to the `/auth/xxxx/login` path + resp = s.get(redirect_url_obj.geturl(), allow_redirects=True) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}" + ) + + # set the login url + auth_session["dex_login_url"] = resp.url + + ################ + # Attempt Dex Login + ################ + resp = s.post( + auth_session["dex_login_url"], + data={"login": username, "password": password}, + allow_redirects=True + ) + if len(resp.history) == 0: + raise RuntimeError( + f"Login credentials were probably invalid - " + f"No redirect after POST to: {auth_session['dex_login_url']}" + ) + + # store the session cookies in a "key1=value1; key2=value2" string + auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies]) + + return auth_session \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py b/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py new file mode 100644 index 000000000..3c7c0dfdc --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py @@ -0,0 +1,19 @@ +import os +import requests + +from typing import TypedDict + +def retrieve_namespaces(host: str, auth_session: TypedDict) -> str: + workgroup_endpoint = os.path.join(host, "api/workgroup/env-info") + + cookies = {} + cookie_tokens = auth_session["session_cookie"].split("=") + print(cookie_tokens[0]) + cookies[cookie_tokens[0]]=cookie_tokens[1] + resp = requests.get(workgroup_endpoint, cookies=cookies) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}" + ) + return [ns["namespace"] for ns in resp.json()["namespaces"] if + ns["role"]=="owner"] \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/mnist.py b/kubeflow/examples/1.connect-kubeflow/py/mnist.py new file mode 100644 index 000000000..fc2911a05 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/mnist.py @@ -0,0 +1,132 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "https://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for mnist." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/mnist_pipeline.yaml' + name='pipeline-' + random_suffix() + description="This is a mnist pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'mnist' + random_suffix() + description = "This is a mnist run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'client-last_accuracy': + output_value = parameter['value'] + + if output_value is not None: + print(f"fl Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml new file mode 100644 index 000000000..11f53462f --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml @@ -0,0 +1,651 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: fl-test- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2024-01-02T05:53:41.650368', + pipelines.kubeflow.org/pipeline_spec: '{"inputs": [{"default": "kubeflow-user-thu01", + "name": "namespace", "optional": true}], "name": "FL test"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} +spec: + entrypoint: fl-test + templates: + - name: client + container: + args: [--batch, '1', '----output-paths', /tmp/outputs/last_accuracy/data] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def client(batch):\n import json\n import requests\n import time\n\ + \ import pandas as pd\n import numpy as np\n import tensorflow as\ + \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ + \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ + \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ + \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ + \ tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import\ + \ Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras\ + \ import backend as K\n\n normal_url='https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'\ + \ \n abnormal_url='https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download'\n\ + \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ + \ num_features = len(normal_data.columns)\n print(num_features)\n \ + \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ + \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ + \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ + \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ + \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ + \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ + \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ + \n input_shape = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n\ + \ @staticmethod\n def build(shape, classes):\n model\ + \ = Sequential()\n model.add(LSTM(units=64, input_shape=input_shape,\ + \ return_sequences=True))\n model.add(Dropout(0.2))\n \ + \ model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n \ + \ model.add(Dense(units=num_classes, activation='softmax'))\n\n \ + \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ + \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ + \ #The client should have its own data, not like this. It's a lazy method.\n\ + \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ + \n #seperate shard into data and labels lists\n data, label\ + \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ + \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ + \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ + \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ + \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ + \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ + \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ + \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ + \ \n optimizer=optimizer, \n metrics=metrics)\n\ + \n if(comm_round == 0):\n history = client_model.fit(dataset,\ + \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ + \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ + \ test_loss, test_accuracy = client_model.evaluate(dataset)\n \ + \ print(f'Test accuracy: {test_accuracy}')\n\n local_weight = client_model.get_weights()\n\ + \ local_weight = [np.array(w).tolist() for w in local_weight]\n\n \ + \ client_data = {\"local_count\": local_count,'bs': bs, 'local_weight':\ + \ json.dumps(local_weight)}\n\n while True:\n try:\n \ + \ weight = (requests.post(server_url,data=client_data))\n\n \ + \ if weight.status_code == 200:\n print(f\"\ + exist\")\n\n break\n else:\n \ + \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ + \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ + \ data = weight.json()\n avg_weight = data.get('result')\n \ + \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ + \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ + \ \n try:\n response = requests.get(shutdown_url)\n except\ + \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ + \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ + \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ + \ str:\n if isinstance(float_value, str):\n return float_value\n\ + \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ + \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ + \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ + _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ + --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ + _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ + \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ + _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ + \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + outputs: + parameters: + - name: client-last_accuracy + valueFrom: {path: /tmp/outputs/last_accuracy/data} + artifacts: + - {name: client-last_accuracy, path: /tmp/outputs/last_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": + "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 + python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' + || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def client(batch):\n import json\n import requests\n import time\n import + pandas as pd\n import numpy as np\n import tensorflow as tf\n from + tensorflow.keras.models import Sequential\n from tensorflow.keras.layers + import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from + tensorflow.keras.layers import Activation\n from tensorflow.keras.layers + import Flatten\n from tensorflow.keras.layers import Dense\n from + tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import + Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras + import backend as K\n\n normal_url=''https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'' + \n abnormal_url=''https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download''\n normal_data + = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features + = len(normal_data.columns)\n print(num_features)\n normal_label = + np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, + 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label + = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data + = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), + num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data + = list(zip(data, data_label))\n data_length=len(full_data)\n\n input_shape + = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n @staticmethod\n def + build(shape, classes):\n model = Sequential()\n model.add(LSTM(units=64, + input_shape=input_shape, return_sequences=True))\n model.add(Dropout(0.2))\n model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n model.add(Dense(units=num_classes, + activation=''softmax''))\n\n return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] + #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] + #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data + len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate + shard into data and labels lists\n data, label = zip(*data_shard)\n dataset + = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return + dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs + = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics + = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for + comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model + = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, + \n metrics=metrics)\n\n if(comm_round == 0):\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n\n test_loss, test_accuracy + = client_model.evaluate(dataset)\n print(f''Test accuracy: {test_accuracy}'')\n\n local_weight + = client_model.get_weights()\n local_weight = [np.array(w).tolist() + for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': + bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight + = (requests.post(server_url,data=client_data))\n\n if weight.status_code + == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server + error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not + exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight + = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight + = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response + = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already + shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef + _serialize_float(float_value: float) -> str:\n if isinstance(float_value, + str):\n return float_value\n if not isinstance(float_value, (float, + int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + float.''.format(\n str(float_value), str(type(float_value))))\n return + str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', + description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, + required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": + "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": + "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": + "1"}'} + - name: client-2 + container: + args: [--batch, '2', '----output-paths', /tmp/outputs/last_accuracy/data] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def client(batch):\n import json\n import requests\n import time\n\ + \ import pandas as pd\n import numpy as np\n import tensorflow as\ + \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ + \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ + \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ + \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ + \ tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import\ + \ Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras\ + \ import backend as K\n\n normal_url='https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'\ + \ \n abnormal_url='https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download'\n\ + \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ + \ num_features = len(normal_data.columns)\n print(num_features)\n \ + \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ + \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ + \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ + \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ + \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ + \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ + \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ + \n input_shape = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n\ + \ @staticmethod\n def build(shape, classes):\n model\ + \ = Sequential()\n model.add(LSTM(units=64, input_shape=input_shape,\ + \ return_sequences=True))\n model.add(Dropout(0.2))\n \ + \ model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n \ + \ model.add(Dense(units=num_classes, activation='softmax'))\n\n \ + \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ + \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ + \ #The client should have its own data, not like this. It's a lazy method.\n\ + \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ + \n #seperate shard into data and labels lists\n data, label\ + \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ + \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ + \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ + \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ + \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ + \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ + \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ + \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ + \ \n optimizer=optimizer, \n metrics=metrics)\n\ + \n if(comm_round == 0):\n history = client_model.fit(dataset,\ + \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ + \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ + \ test_loss, test_accuracy = client_model.evaluate(dataset)\n \ + \ print(f'Test accuracy: {test_accuracy}')\n\n local_weight = client_model.get_weights()\n\ + \ local_weight = [np.array(w).tolist() for w in local_weight]\n\n \ + \ client_data = {\"local_count\": local_count,'bs': bs, 'local_weight':\ + \ json.dumps(local_weight)}\n\n while True:\n try:\n \ + \ weight = (requests.post(server_url,data=client_data))\n\n \ + \ if weight.status_code == 200:\n print(f\"\ + exist\")\n\n break\n else:\n \ + \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ + \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ + \ data = weight.json()\n avg_weight = data.get('result')\n \ + \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ + \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ + \ \n try:\n response = requests.get(shutdown_url)\n except\ + \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ + \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ + \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ + \ str:\n if isinstance(float_value, str):\n return float_value\n\ + \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ + \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ + \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ + _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ + --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ + _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ + \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ + _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ + \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + outputs: + artifacts: + - {name: client-2-last_accuracy, path: /tmp/outputs/last_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": + "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 + python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' + || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def client(batch):\n import json\n import requests\n import time\n import + pandas as pd\n import numpy as np\n import tensorflow as tf\n from + tensorflow.keras.models import Sequential\n from tensorflow.keras.layers + import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from + tensorflow.keras.layers import Activation\n from tensorflow.keras.layers + import Flatten\n from tensorflow.keras.layers import Dense\n from + tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import + Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras + import backend as K\n\n normal_url=''https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'' + \n abnormal_url=''https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download''\n normal_data + = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features + = len(normal_data.columns)\n print(num_features)\n normal_label = + np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, + 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label + = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data + = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), + num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data + = list(zip(data, data_label))\n data_length=len(full_data)\n\n input_shape + = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n @staticmethod\n def + build(shape, classes):\n model = Sequential()\n model.add(LSTM(units=64, + input_shape=input_shape, return_sequences=True))\n model.add(Dropout(0.2))\n model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n model.add(Dense(units=num_classes, + activation=''softmax''))\n\n return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] + #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] + #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data + len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate + shard into data and labels lists\n data, label = zip(*data_shard)\n dataset + = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return + dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs + = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics + = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for + comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model + = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, + \n metrics=metrics)\n\n if(comm_round == 0):\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n\n test_loss, test_accuracy + = client_model.evaluate(dataset)\n print(f''Test accuracy: {test_accuracy}'')\n\n local_weight + = client_model.get_weights()\n local_weight = [np.array(w).tolist() + for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': + bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight + = (requests.post(server_url,data=client_data))\n\n if weight.status_code + == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server + error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not + exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight + = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight + = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response + = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already + shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef + _serialize_float(float_value: float) -> str:\n if isinstance(float_value, + str):\n return float_value\n if not isinstance(float_value, (float, + int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + float.''.format(\n str(float_value), str(type(float_value))))\n return + str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', + description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, + required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": + "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": + "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": + "2"}'} + - name: delete-service + resource: + action: delete + flags: [--wait=false] + manifest: | + apiVersion: v1 + kind: Service + metadata: + name: http-service + spec: + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + selector: + app: http-service + type: NodePort + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: fl-test + dag: + tasks: + - {name: client, template: client} + - {name: client-2, template: client-2} + - name: delete-service + template: delete-service + dependencies: [server] + - {name: http-service, template: http-service} + - name: server + template: server + dependencies: [http-service] + - name: show-results + template: show-results + dependencies: [client] + arguments: + parameters: + - {name: client-last_accuracy, value: '{{tasks.client.outputs.parameters.client-last_accuracy}}'} + - name: http-service + resource: + action: create + manifest: | + apiVersion: v1 + kind: Service + metadata: + name: http-service + spec: + ports: + - port: 5000 + protocol: TCP + targetPort: 8080 + selector: + app: http-service + outputs: + parameters: + - name: http-service-manifest + valueFrom: {jsonPath: '{}'} + - name: http-service-name + valueFrom: {jsonPath: '{.metadata.name}'} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: server + container: + args: [] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'flask' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'flask' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def server():\n import json\n import pandas as pd\n import numpy\ + \ as np\n import pickle\n import threading\n import time\n import\ + \ tensorflow as tf\n from flask import Flask, jsonify,request\n import\ + \ os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list\ + \ = []\n global_value = { #Share variable\n 'last_run_statue'\ + \ : False, #last run finish or not\n 'data_statue' : None,\ + \ #global_count finish or not\n 'global_count' : None,\n\ + \ 'scale_statue' : None,\n 'weight_statue'\ + \ : None,\n 'average_weights' : None,\n \ + \ 'shutdown' : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n \ + \ init_lock = threading.Lock()\n clients_local_count_lock = threading.Lock()\n\ + \ scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock\ + \ = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n\ + \ def before_request():\n print('get request')\n\n @app.route('/data',\ + \ methods=['POST'])\n def flask_server():\n with init_lock: #check\ + \ last run is finish and init varible\n\n while True:\n\n \ + \ if(len(clients_local_count)==0 and global_value['last_run_statue']\ + \ == False):#init the variable by first client enter\n \ + \ global_value['last_run_statue'] = True\n global_value['data_statue']\ + \ = False\n global_value['scale_statue'] = False\n \ + \ global_value['weight_statue'] = False\n \ + \ break\n\n elif(global_value['last_run_statue'] == True):\n\ + \ break\n time.sleep(3)\n\n local_count\ + \ = int(request.form.get('local_count')) #get data\n bs =\ + \ int(request.form.get('bs'))\n local_weight = json.loads(request.form.get('local_weight'))\n\ + \ local_weight = [np.array(lst) for lst in local_weight]\n\n \ + \ def scale_model_weights(weight, scalar):\n weight_final = []\n\ + \ steps = len(weight)\n for i in range(steps):\n \ + \ weight_final.append(scalar * weight[i])\n return\ + \ weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n \ + \ avg_grad = list()\n #get the average grad accross all\ + \ client gradients\n for grad_list_tuple in zip(*scaled_weight_list):\n\ + \ layer_mean = tf.math.reduce_sum(grad_list_tuple, axis=0)\n\ + \ avg_grad.append(layer_mean)\n\n return avg_grad\n\ + \n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\ + \n with scaled_local_weight_list_lock:\n while True:\n\n\ + \ if (len(clients_local_count) == NUM_OF_CLIENTS and global_value['data_statue']\ + \ != True):\n global_value['last_run_statue'] = False\n\ + \ sum_of_local_count=sum(clients_local_count)\n\n \ + \ global_value['global_count'] = sum_of_local_count \n\n\ + \ scaling_factor=local_count/global_value['global_count']\n\ + \ scaled_weights = scale_model_weights(local_weight, scaling_factor)\n\ + \ scaled_local_weight_list.append(scaled_weights)\n\n \ + \ global_value['scale_statue'] = True \n \ + \ global_value['data_statue'] = True\n break\n \ + \ elif (global_value['data_statue'] == True and global_value['scale_statue']\ + \ == True):\n scaling_factor=local_count/global_value['global_count']\n\ + \ scaled_weights =scale_model_weights(local_weight, scaling_factor)\n\ + \ scaled_local_weight_list.append(scaled_weights)\n\n \ + \ break\n time.sleep(1)\n\n with cal_weight_lock:\n\ + \n while True:\n if(len(scaled_local_weight_list)\ + \ == NUM_OF_CLIENTS and global_value['weight_statue'] != True):\n\n \ + \ global_value['average_weights'] = sum_scaled_weights(scaled_local_weight_list)\n\ + \ global_value['weight_statue'] = True\n \ + \ global_value['average_weights'] = json.dumps([np.array(w).tolist()\ + \ for w in global_value['average_weights']])\n\n break\n\ + \n elif(global_value['weight_statue'] == True):\n\n \ + \ break\n\n time.sleep(1)\n\n clients_local_count.clear()\n\ + \ scaled_local_weight_list.clear()\n\n return jsonify({'result':\ + \ (global_value['average_weights'])})\n\n @app.route('/shutdown', methods=['GET'])\n\ + \ def shutdown_server():\n global_value['shutdown'] +=1 \n \ + \ with shutdown_lock:\n while True:\n if(global_value['shutdown']\ + \ == NUM_OF_CLIENTS):\n os._exit(0)\n \ + \ return 'Server shutting down...'\n time.sleep(1)\n\n \ + \ app.run(host=\"0.0.0.0\", port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Server',\ + \ description='')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs =\ + \ server(**_parsed_args)\n" + image: tensorflow/tensorflow + ports: + - {containerPort: 8080, name: my-port} + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + metadata: + labels: + app: http-service + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": [], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 python3 + -m pip install --quiet --no-warn-script-location ''flask'' ''pandas'' || + PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''flask'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def server():\n import json\n import pandas as pd\n import numpy + as np\n import pickle\n import threading\n import time\n import + tensorflow as tf\n from flask import Flask, jsonify,request\n import + os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list + = []\n global_value = { #Share variable\n ''last_run_statue'' + : False, #last run finish or not\n ''data_statue'' : + None, #global_count finish or not\n ''global_count'' + : None,\n ''scale_statue'' : None,\n ''weight_statue'' + : None,\n ''average_weights'' : None,\n ''shutdown'' + : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n init_lock = threading.Lock()\n clients_local_count_lock + = threading.Lock()\n scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock + = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n def + before_request():\n print(''get request'')\n\n @app.route(''/data'', + methods=[''POST''])\n def flask_server():\n with init_lock: #check + last run is finish and init varible\n\n while True:\n\n if(len(clients_local_count)==0 + and global_value[''last_run_statue''] == False):#init the variable by first + client enter\n global_value[''last_run_statue''] = True\n global_value[''data_statue''] + = False\n global_value[''scale_statue''] = False\n global_value[''weight_statue''] + = False\n break\n\n elif(global_value[''last_run_statue''] + == True):\n break\n time.sleep(3)\n\n local_count + = int(request.form.get(''local_count'')) #get data\n bs + = int(request.form.get(''bs''))\n local_weight = json.loads(request.form.get(''local_weight''))\n local_weight + = [np.array(lst) for lst in local_weight]\n\n def scale_model_weights(weight, + scalar):\n weight_final = []\n steps = len(weight)\n for + i in range(steps):\n weight_final.append(scalar * weight[i])\n return + weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n avg_grad + = list()\n #get the average grad accross all client gradients\n for + grad_list_tuple in zip(*scaled_weight_list):\n layer_mean + = tf.math.reduce_sum(grad_list_tuple, axis=0)\n avg_grad.append(layer_mean)\n\n return + avg_grad\n\n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\n with + scaled_local_weight_list_lock:\n while True:\n\n if + (len(clients_local_count) == NUM_OF_CLIENTS and global_value[''data_statue''] + != True):\n global_value[''last_run_statue''] = False\n sum_of_local_count=sum(clients_local_count)\n\n global_value[''global_count''] + = sum_of_local_count \n\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights + = scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n global_value[''scale_statue''] + = True \n global_value[''data_statue''] = True\n break\n elif + (global_value[''data_statue''] == True and global_value[''scale_statue''] + == True):\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights + =scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n break\n time.sleep(1)\n\n with + cal_weight_lock:\n\n while True:\n if(len(scaled_local_weight_list) + == NUM_OF_CLIENTS and global_value[''weight_statue''] != True):\n\n global_value[''average_weights''] + = sum_scaled_weights(scaled_local_weight_list)\n global_value[''weight_statue''] + = True\n global_value[''average_weights''] = json.dumps([np.array(w).tolist() + for w in global_value[''average_weights'']])\n\n break\n\n elif(global_value[''weight_statue''] + == True):\n\n break\n\n time.sleep(1)\n\n clients_local_count.clear()\n scaled_local_weight_list.clear()\n\n return + jsonify({''result'': (global_value[''average_weights''])})\n\n @app.route(''/shutdown'', + methods=[''GET''])\n def shutdown_server():\n global_value[''shutdown''] + +=1 \n with shutdown_lock:\n while True:\n if(global_value[''shutdown''] + == NUM_OF_CLIENTS):\n os._exit(0)\n return + ''Server shutting down...''\n time.sleep(1)\n\n app.run(host=\"0.0.0.0\", + port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Server'', + description='''')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs + = server(**_parsed_args)\n"], "image": "tensorflow/tensorflow"}}, "name": + "Server"}', pipelines.kubeflow.org/component_ref: '{}'} + - name: show-results + container: + args: [--test-acc, '{{inputs.parameters.client-last_accuracy}}', '----output-paths', + /tmp/outputs/test_accuracy/data] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - | + def show_results(test_acc): + return([test_acc]) + + def _serialize_float(float_value: float) -> str: + if isinstance(float_value, str): + return float_value + if not isinstance(float_value, (float, int)): + raise TypeError('Value "{}" has type "{}" instead of float.'.format( + str(float_value), str(type(float_value)))) + return str(float_value) + + import argparse + _parser = argparse.ArgumentParser(prog='Show results', description='') + _parser.add_argument("--test-acc", dest="test_acc", type=float, required=True, default=argparse.SUPPRESS) + _parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=1) + _parsed_args = vars(_parser.parse_args()) + _output_files = _parsed_args.pop("_output_paths", []) + + _outputs = show_results(**_parsed_args) + + _output_serializers = [ + _serialize_float, + + ] + + import os + for idx, output_file in enumerate(_output_files): + try: + os.makedirs(os.path.dirname(output_file)) + except OSError: + pass + with open(output_file, 'w') as f: + f.write(_output_serializers[idx](_outputs[idx])) + image: python:3.7 + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + inputs: + parameters: + - {name: client-last_accuracy} + outputs: + artifacts: + - {name: show-results-test_accuracy, path: /tmp/outputs/test_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--test-acc", {"inputValue": "test_acc"}, "----output-paths", + {"outputPath": "test_accuracy"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def show_results(test_acc):\n return([test_acc])\n\ndef _serialize_float(float_value: + float) -> str:\n if isinstance(float_value, str):\n return float_value\n if + not isinstance(float_value, (float, int)):\n raise TypeError(''Value + \"{}\" has type \"{}\" instead of float.''.format(\n str(float_value), + str(type(float_value))))\n return str(float_value)\n\nimport argparse\n_parser + = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--test-acc\", + dest=\"test_acc\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = show_results(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "python:3.7"}}, "inputs": [{"name": "test_acc", "type": "Float"}], + "name": "Show results", "outputs": [{"name": "test_accuracy", "type": "Float"}]}', + pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"test_acc": + "{{inputs.parameters.client-last_accuracy}}"}'} + arguments: + parameters: + - {name: namespace, value: kubeflow-user-thu01} + serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml new file mode 100644 index 000000000..8381600f3 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml @@ -0,0 +1,639 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: fl-test- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-12-13T03:33:40.267552', + pipelines.kubeflow.org/pipeline_spec: '{"inputs": [{"default": "kubeflow-user-thu01", + "name": "namespace", "optional": true}], "name": "FL test"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} +spec: + entrypoint: fl-test + templates: + - name: client + container: + args: [--batch, '1', '----output-paths', /tmp/outputs/last_accuracy/data] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def client(batch):\n import json\n import requests\n import time\n\ + \ import pandas as pd\n import numpy as np\n import tensorflow as\ + \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ + \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ + \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ + \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ + \ tensorflow.keras.optimizers import SGD\n from tensorflow.keras import\ + \ backend as K\n\n normal_url='https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'\ + \ \n abnormal_url='https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy'\n\ + \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ + \ num_features = len(normal_data.columns)\n print(num_features)\n \ + \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ + \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ + \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ + \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ + \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ + \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ + \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ + \n class SimpleMLP:\n @staticmethod\n def build(shape, classes):\n\ + \ model = Sequential()\n model.add(Conv1D(filters=4,\ + \ kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n\ + \ model.add(Flatten())\n model.add(Dense(8, activation=\"\ + relu\"))\n model.add(Dense(2, activation = 'softmax'))\n\n \ + \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ + \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ + \ #The client should have its own data, not like this. It's a lazy method.\n\ + \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ + \n #seperate shard into data and labels lists\n data, label\ + \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ + \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ + \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ + \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ + \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ + \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ + \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ + \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ + \ \n optimizer=optimizer, \n metrics=metrics)\n\ + \n if(comm_round == 0):\n history = client_model.fit(dataset,\ + \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ + \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ + \ local_weight = client_model.get_weights()\n local_weight =\ + \ [np.array(w).tolist() for w in local_weight]\n\n client_data = {\"\ + local_count\": local_count,'bs': bs, 'local_weight': json.dumps(local_weight)}\n\ + \n while True:\n try:\n weight = (requests.post(server_url,data=client_data))\n\ + \n if weight.status_code == 200:\n print(f\"\ + exist\")\n\n break\n else:\n \ + \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ + \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ + \ data = weight.json()\n avg_weight = data.get('result')\n \ + \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ + \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ + \ \n try:\n response = requests.get(shutdown_url)\n except\ + \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ + \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ + \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ + \ str:\n if isinstance(float_value, str):\n return float_value\n\ + \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ + \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ + \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ + _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ + --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ + _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ + \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ + _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ + \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + outputs: + parameters: + - name: client-last_accuracy + valueFrom: {path: /tmp/outputs/last_accuracy/data} + artifacts: + - {name: client-last_accuracy, path: /tmp/outputs/last_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": + "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 + python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' + || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def client(batch):\n import json\n import requests\n import time\n import + pandas as pd\n import numpy as np\n import tensorflow as tf\n from + tensorflow.keras.models import Sequential\n from tensorflow.keras.layers + import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from + tensorflow.keras.layers import Activation\n from tensorflow.keras.layers + import Flatten\n from tensorflow.keras.layers import Dense\n from + tensorflow.keras.optimizers import SGD\n from tensorflow.keras import + backend as K\n\n normal_url=''https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'' + \n abnormal_url=''https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy''\n normal_data + = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features + = len(normal_data.columns)\n print(num_features)\n normal_label = + np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, + 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label + = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data + = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), + num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data + = list(zip(data, data_label))\n data_length=len(full_data)\n\n class + SimpleMLP:\n @staticmethod\n def build(shape, classes):\n model + = Sequential()\n model.add(Conv1D(filters=4, kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n model.add(Flatten())\n model.add(Dense(8, + activation=\"relu\"))\n model.add(Dense(2, activation = ''softmax''))\n\n return + model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] + #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] + #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data + len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate + shard into data and labels lists\n data, label = zip(*data_shard)\n dataset + = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return + dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs + = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics + = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for + comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model + = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, + \n metrics=metrics)\n\n if(comm_round == 0):\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n\n local_weight + = client_model.get_weights()\n local_weight = [np.array(w).tolist() + for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': + bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight + = (requests.post(server_url,data=client_data))\n\n if weight.status_code + == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server + error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not + exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight + = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight + = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response + = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already + shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef + _serialize_float(float_value: float) -> str:\n if isinstance(float_value, + str):\n return float_value\n if not isinstance(float_value, (float, + int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + float.''.format(\n str(float_value), str(type(float_value))))\n return + str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', + description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, + required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": + "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": + "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": + "1"}'} + - name: client-2 + container: + args: [--batch, '2', '----output-paths', /tmp/outputs/last_accuracy/data] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def client(batch):\n import json\n import requests\n import time\n\ + \ import pandas as pd\n import numpy as np\n import tensorflow as\ + \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ + \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ + \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ + \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ + \ tensorflow.keras.optimizers import SGD\n from tensorflow.keras import\ + \ backend as K\n\n normal_url='https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'\ + \ \n abnormal_url='https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy'\n\ + \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ + \ num_features = len(normal_data.columns)\n print(num_features)\n \ + \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ + \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ + \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ + \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ + \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ + \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ + \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ + \n class SimpleMLP:\n @staticmethod\n def build(shape, classes):\n\ + \ model = Sequential()\n model.add(Conv1D(filters=4,\ + \ kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n\ + \ model.add(Flatten())\n model.add(Dense(8, activation=\"\ + relu\"))\n model.add(Dense(2, activation = 'softmax'))\n\n \ + \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ + \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ + \ #The client should have its own data, not like this. It's a lazy method.\n\ + \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ + \n #seperate shard into data and labels lists\n data, label\ + \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ + \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ + \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ + \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ + \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ + \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ + \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ + \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ + \ \n optimizer=optimizer, \n metrics=metrics)\n\ + \n if(comm_round == 0):\n history = client_model.fit(dataset,\ + \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ + \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ + \ local_weight = client_model.get_weights()\n local_weight =\ + \ [np.array(w).tolist() for w in local_weight]\n\n client_data = {\"\ + local_count\": local_count,'bs': bs, 'local_weight': json.dumps(local_weight)}\n\ + \n while True:\n try:\n weight = (requests.post(server_url,data=client_data))\n\ + \n if weight.status_code == 200:\n print(f\"\ + exist\")\n\n break\n else:\n \ + \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ + \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ + \ data = weight.json()\n avg_weight = data.get('result')\n \ + \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ + \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ + \ \n try:\n response = requests.get(shutdown_url)\n except\ + \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ + \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ + \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ + \ str:\n if isinstance(float_value, str):\n return float_value\n\ + \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ + \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ + \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ + _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ + --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ + _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ + \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ + _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ + \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + outputs: + artifacts: + - {name: client-2-last_accuracy, path: /tmp/outputs/last_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": + "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 + python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' + || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def client(batch):\n import json\n import requests\n import time\n import + pandas as pd\n import numpy as np\n import tensorflow as tf\n from + tensorflow.keras.models import Sequential\n from tensorflow.keras.layers + import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from + tensorflow.keras.layers import Activation\n from tensorflow.keras.layers + import Flatten\n from tensorflow.keras.layers import Dense\n from + tensorflow.keras.optimizers import SGD\n from tensorflow.keras import + backend as K\n\n normal_url=''https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'' + \n abnormal_url=''https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy''\n normal_data + = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features + = len(normal_data.columns)\n print(num_features)\n normal_label = + np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, + 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label + = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data + = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), + num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data + = list(zip(data, data_label))\n data_length=len(full_data)\n\n class + SimpleMLP:\n @staticmethod\n def build(shape, classes):\n model + = Sequential()\n model.add(Conv1D(filters=4, kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n model.add(Flatten())\n model.add(Dense(8, + activation=\"relu\"))\n model.add(Dense(2, activation = ''softmax''))\n\n return + model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] + #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] + #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data + len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate + shard into data and labels lists\n data, label = zip(*data_shard)\n dataset + = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return + dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs + = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics + = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for + comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model + = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, + \n metrics=metrics)\n\n if(comm_round == 0):\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n\n local_weight + = client_model.get_weights()\n local_weight = [np.array(w).tolist() + for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': + bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight + = (requests.post(server_url,data=client_data))\n\n if weight.status_code + == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server + error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not + exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight + = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight + = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response + = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already + shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef + _serialize_float(float_value: float) -> str:\n if isinstance(float_value, + str):\n return float_value\n if not isinstance(float_value, (float, + int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + float.''.format(\n str(float_value), str(type(float_value))))\n return + str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', + description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, + required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": + "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": + "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": + "2"}'} + - name: delete-service + resource: + action: delete + flags: [--wait=false] + manifest: | + apiVersion: v1 + kind: Service + metadata: + name: http-service + spec: + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + selector: + app: http-service + type: NodePort + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: fl-test + dag: + tasks: + - {name: client, template: client} + - {name: client-2, template: client-2} + - name: delete-service + template: delete-service + dependencies: [server] + - {name: http-service, template: http-service} + - name: server + template: server + dependencies: [http-service] + - name: show-results + template: show-results + dependencies: [client] + arguments: + parameters: + - {name: client-last_accuracy, value: '{{tasks.client.outputs.parameters.client-last_accuracy}}'} + - name: http-service + resource: + action: create + manifest: | + apiVersion: v1 + kind: Service + metadata: + name: http-service + spec: + ports: + - port: 5000 + protocol: TCP + targetPort: 8080 + selector: + app: http-service + outputs: + parameters: + - name: http-service-manifest + valueFrom: {jsonPath: '{}'} + - name: http-service-name + valueFrom: {jsonPath: '{.metadata.name}'} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: server + container: + args: [] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'flask' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'flask' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def server():\n import json\n import pandas as pd\n import numpy\ + \ as np\n import pickle\n import threading\n import time\n import\ + \ tensorflow as tf\n from flask import Flask, jsonify,request\n import\ + \ os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list\ + \ = []\n global_value = { #Share variable\n 'last_run_statue'\ + \ : False, #last run finish or not\n 'data_statue' : None,\ + \ #global_count finish or not\n 'global_count' : None,\n\ + \ 'scale_statue' : None,\n 'weight_statue'\ + \ : None,\n 'average_weights' : None,\n \ + \ 'shutdown' : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n \ + \ init_lock = threading.Lock()\n clients_local_count_lock = threading.Lock()\n\ + \ scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock\ + \ = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n\ + \ def before_request():\n print('get request')\n\n @app.route('/data',\ + \ methods=['POST'])\n def flask_server():\n with init_lock: #check\ + \ last run is finish and init varible\n\n while True:\n\n \ + \ if(len(clients_local_count)==0 and global_value['last_run_statue']\ + \ == False):#init the variable by first client enter\n \ + \ global_value['last_run_statue'] = True\n global_value['data_statue']\ + \ = False\n global_value['scale_statue'] = False\n \ + \ global_value['weight_statue'] = False\n \ + \ break\n\n elif(global_value['last_run_statue'] == True):\n\ + \ break\n time.sleep(3)\n\n local_count\ + \ = int(request.form.get('local_count')) #get data\n bs =\ + \ int(request.form.get('bs'))\n local_weight = json.loads(request.form.get('local_weight'))\n\ + \ local_weight = [np.array(lst) for lst in local_weight]\n\n \ + \ def scale_model_weights(weight, scalar):\n weight_final = []\n\ + \ steps = len(weight)\n for i in range(steps):\n \ + \ weight_final.append(scalar * weight[i])\n return\ + \ weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n \ + \ avg_grad = list()\n #get the average grad accross all\ + \ client gradients\n for grad_list_tuple in zip(*scaled_weight_list):\n\ + \ layer_mean = tf.math.reduce_sum(grad_list_tuple, axis=0)\n\ + \ avg_grad.append(layer_mean)\n\n return avg_grad\n\ + \n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\ + \n with scaled_local_weight_list_lock:\n while True:\n\n\ + \ if (len(clients_local_count) == NUM_OF_CLIENTS and global_value['data_statue']\ + \ != True):\n global_value['last_run_statue'] = False\n\ + \ sum_of_local_count=sum(clients_local_count)\n\n \ + \ global_value['global_count'] = sum_of_local_count \n\n\ + \ scaling_factor=local_count/global_value['global_count']\n\ + \ scaled_weights = scale_model_weights(local_weight, scaling_factor)\n\ + \ scaled_local_weight_list.append(scaled_weights)\n\n \ + \ global_value['scale_statue'] = True \n \ + \ global_value['data_statue'] = True\n break\n \ + \ elif (global_value['data_statue'] == True and global_value['scale_statue']\ + \ == True):\n scaling_factor=local_count/global_value['global_count']\n\ + \ scaled_weights =scale_model_weights(local_weight, scaling_factor)\n\ + \ scaled_local_weight_list.append(scaled_weights)\n\n \ + \ break\n time.sleep(1)\n\n with cal_weight_lock:\n\ + \n while True:\n if(len(scaled_local_weight_list)\ + \ == NUM_OF_CLIENTS and global_value['weight_statue'] != True):\n\n \ + \ global_value['average_weights'] = sum_scaled_weights(scaled_local_weight_list)\n\ + \ global_value['weight_statue'] = True\n \ + \ global_value['average_weights'] = json.dumps([np.array(w).tolist()\ + \ for w in global_value['average_weights']])\n\n break\n\ + \n elif(global_value['weight_statue'] == True):\n\n \ + \ break\n\n time.sleep(1)\n\n clients_local_count.clear()\n\ + \ scaled_local_weight_list.clear()\n\n return jsonify({'result':\ + \ (global_value['average_weights'])})\n\n @app.route('/shutdown', methods=['GET'])\n\ + \ def shutdown_server():\n global_value['shutdown'] +=1 \n \ + \ with shutdown_lock:\n while True:\n if(global_value['shutdown']\ + \ == NUM_OF_CLIENTS):\n os._exit(0)\n \ + \ return 'Server shutting down...'\n time.sleep(1)\n\n \ + \ app.run(host=\"0.0.0.0\", port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Server',\ + \ description='')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs =\ + \ server(**_parsed_args)\n" + image: tensorflow/tensorflow + ports: + - {containerPort: 8080, name: my-port} + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + metadata: + labels: + app: http-service + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": [], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 python3 + -m pip install --quiet --no-warn-script-location ''flask'' ''pandas'' || + PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''flask'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def server():\n import json\n import pandas as pd\n import numpy + as np\n import pickle\n import threading\n import time\n import + tensorflow as tf\n from flask import Flask, jsonify,request\n import + os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list + = []\n global_value = { #Share variable\n ''last_run_statue'' + : False, #last run finish or not\n ''data_statue'' : + None, #global_count finish or not\n ''global_count'' + : None,\n ''scale_statue'' : None,\n ''weight_statue'' + : None,\n ''average_weights'' : None,\n ''shutdown'' + : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n init_lock = threading.Lock()\n clients_local_count_lock + = threading.Lock()\n scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock + = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n def + before_request():\n print(''get request'')\n\n @app.route(''/data'', + methods=[''POST''])\n def flask_server():\n with init_lock: #check + last run is finish and init varible\n\n while True:\n\n if(len(clients_local_count)==0 + and global_value[''last_run_statue''] == False):#init the variable by first + client enter\n global_value[''last_run_statue''] = True\n global_value[''data_statue''] + = False\n global_value[''scale_statue''] = False\n global_value[''weight_statue''] + = False\n break\n\n elif(global_value[''last_run_statue''] + == True):\n break\n time.sleep(3)\n\n local_count + = int(request.form.get(''local_count'')) #get data\n bs + = int(request.form.get(''bs''))\n local_weight = json.loads(request.form.get(''local_weight''))\n local_weight + = [np.array(lst) for lst in local_weight]\n\n def scale_model_weights(weight, + scalar):\n weight_final = []\n steps = len(weight)\n for + i in range(steps):\n weight_final.append(scalar * weight[i])\n return + weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n avg_grad + = list()\n #get the average grad accross all client gradients\n for + grad_list_tuple in zip(*scaled_weight_list):\n layer_mean + = tf.math.reduce_sum(grad_list_tuple, axis=0)\n avg_grad.append(layer_mean)\n\n return + avg_grad\n\n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\n with + scaled_local_weight_list_lock:\n while True:\n\n if + (len(clients_local_count) == NUM_OF_CLIENTS and global_value[''data_statue''] + != True):\n global_value[''last_run_statue''] = False\n sum_of_local_count=sum(clients_local_count)\n\n global_value[''global_count''] + = sum_of_local_count \n\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights + = scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n global_value[''scale_statue''] + = True \n global_value[''data_statue''] = True\n break\n elif + (global_value[''data_statue''] == True and global_value[''scale_statue''] + == True):\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights + =scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n break\n time.sleep(1)\n\n with + cal_weight_lock:\n\n while True:\n if(len(scaled_local_weight_list) + == NUM_OF_CLIENTS and global_value[''weight_statue''] != True):\n\n global_value[''average_weights''] + = sum_scaled_weights(scaled_local_weight_list)\n global_value[''weight_statue''] + = True\n global_value[''average_weights''] = json.dumps([np.array(w).tolist() + for w in global_value[''average_weights'']])\n\n break\n\n elif(global_value[''weight_statue''] + == True):\n\n break\n\n time.sleep(1)\n\n clients_local_count.clear()\n scaled_local_weight_list.clear()\n\n return + jsonify({''result'': (global_value[''average_weights''])})\n\n @app.route(''/shutdown'', + methods=[''GET''])\n def shutdown_server():\n global_value[''shutdown''] + +=1 \n with shutdown_lock:\n while True:\n if(global_value[''shutdown''] + == NUM_OF_CLIENTS):\n os._exit(0)\n return + ''Server shutting down...''\n time.sleep(1)\n\n app.run(host=\"0.0.0.0\", + port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Server'', + description='''')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs + = server(**_parsed_args)\n"], "image": "tensorflow/tensorflow"}}, "name": + "Server"}', pipelines.kubeflow.org/component_ref: '{}'} + - name: show-results + container: + args: [--test-acc, '{{inputs.parameters.client-last_accuracy}}', '----output-paths', + /tmp/outputs/test_accuracy/data] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - | + def show_results(test_acc): + return([test_acc]) + + def _serialize_float(float_value: float) -> str: + if isinstance(float_value, str): + return float_value + if not isinstance(float_value, (float, int)): + raise TypeError('Value "{}" has type "{}" instead of float.'.format( + str(float_value), str(type(float_value)))) + return str(float_value) + + import argparse + _parser = argparse.ArgumentParser(prog='Show results', description='') + _parser.add_argument("--test-acc", dest="test_acc", type=float, required=True, default=argparse.SUPPRESS) + _parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=1) + _parsed_args = vars(_parser.parse_args()) + _output_files = _parsed_args.pop("_output_paths", []) + + _outputs = show_results(**_parsed_args) + + _output_serializers = [ + _serialize_float, + + ] + + import os + for idx, output_file in enumerate(_output_files): + try: + os.makedirs(os.path.dirname(output_file)) + except OSError: + pass + with open(output_file, 'w') as f: + f.write(_output_serializers[idx](_outputs[idx])) + image: python:3.7 + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + inputs: + parameters: + - {name: client-last_accuracy} + outputs: + artifacts: + - {name: show-results-test_accuracy, path: /tmp/outputs/test_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--test-acc", {"inputValue": "test_acc"}, "----output-paths", + {"outputPath": "test_accuracy"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def show_results(test_acc):\n return([test_acc])\n\ndef _serialize_float(float_value: + float) -> str:\n if isinstance(float_value, str):\n return float_value\n if + not isinstance(float_value, (float, int)):\n raise TypeError(''Value + \"{}\" has type \"{}\" instead of float.''.format(\n str(float_value), + str(type(float_value))))\n return str(float_value)\n\nimport argparse\n_parser + = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--test-acc\", + dest=\"test_acc\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = show_results(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "python:3.7"}}, "inputs": [{"name": "test_acc", "type": "Float"}], + "name": "Show results", "outputs": [{"name": "test_accuracy", "type": "Float"}]}', + pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"test_acc": + "{{inputs.parameters.client-last_accuracy}}"}'} + arguments: + parameters: + - {name: namespace, value: kubeflow-user-thu01} + serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml new file mode 100644 index 000000000..b8f353c80 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml @@ -0,0 +1,211 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: mnist-pipeline- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-12-26T13:06:02.352865', + pipelines.kubeflow.org/pipeline_spec: '{"description": "A pipeline to train a + model on mnist dataset and start a tensorboard.", "name": "mnist pipeline"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} +spec: + entrypoint: mnist-pipeline + templates: + - name: create-tensorboard-visualization + container: + args: [] + command: + - sh + - -ex + - -c + - | + log_dir="$0" + output_metadata_path="$1" + pod_template_spec="$2" + image="$3" + + mkdir -p "$(dirname "$output_metadata_path")" + + echo ' + { + "outputs" : [{ + "type": "tensorboard", + "source": "'"$log_dir"'", + "image": "'"$image"'", + "pod_template_spec": '"$pod_template_spec"' + }] + } + ' >"$output_metadata_path" + - volume://mypvc/logs + - /tmp/outputs/mlpipeline-ui-metadata/data + - '{"spec": {"containers": [{"volumeMounts": [{"mountPath": "/data", "name": + "mypvc"}], "resources": {"requests": {"cpu": "250m"}, "limits": {"cpu": "500m"}}}], + "serviceAccountName": "default-editor", "volumes": [{"name": "mypvc", "persistentVolumeClaim": + {"claimName": "my-awesome-kf-workshop-1703595962"}}]}}' + - footprintai/tensorboard:2.7.0 + image: alpine + resources: + limits: {cpu: '1'} + requests: {cpu: '1'} + outputs: + artifacts: + - {name: mlpipeline-ui-metadata, path: /tmp/outputs/mlpipeline-ui-metadata/data} + metadata: + annotations: {author: Alexey Volkov , canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/tensorboard/prepare_tensorboard/component.yaml', + pipelines.kubeflow.org/component_spec: '{"description": "Pre-creates Tensorboard + visualization for a given Log dir URI.\nThis way the Tensorboard can be + viewed before the training completes.\nThe output Log dir URI should be + passed to a trainer component that will write Tensorboard logs to that directory.\n", + "implementation": {"container": {"command": ["sh", "-ex", "-c", "log_dir=\"$0\"\noutput_metadata_path=\"$1\"\npod_template_spec=\"$2\"\nimage=\"$3\"\n\nmkdir + -p \"$(dirname \"$output_metadata_path\")\"\n\necho ''\n {\n \"outputs\" + : [{\n \"type\": \"tensorboard\",\n \"source\": \"''\"$log_dir\"''\",\n \"image\": + \"''\"$image\"''\",\n \"pod_template_spec\": ''\"$pod_template_spec\"''\n }]\n }\n'' + >\"$output_metadata_path\"\n", {"inputValue": "Log dir URI"}, {"outputPath": + "mlpipeline-ui-metadata"}, {"inputValue": "Pod Template Spec"}, {"inputValue": + "Image"}], "image": "alpine"}}, "inputs": [{"name": "Log dir URI", "type": + "String"}, {"default": "", "name": "Image", "type": "String"}, {"default": + "null", "name": "Pod Template Spec", "type": "String"}], "metadata": {"annotations": + {"author": "Alexey Volkov ", "canonical_location": + "https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/tensorboard/prepare_tensorboard/component.yaml"}}, + "name": "Create Tensorboard visualization", "outputs": [{"name": "mlpipeline-ui-metadata", + "type": "kfp.v1.ui-metadata"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "cc3c37c54619129e4f57e4564bc5df0ba9719a305e6145238f2ae7e54d87f2ef", "url": + "https://raw.githubusercontent.com/kubeflow/pipelines/1b107eb4bb2510ecb99fd5f4fb438cbf7c96a87a/components/contrib/tensorflow/tensorboard/prepare_tensorboard/component.yaml"}', + pipelines.kubeflow.org/arguments.parameters: '{"Image": "footprintai/tensorboard:2.7.0", + "Log dir URI": "volume://mypvc/logs", "Pod Template Spec": "{\"spec\": {\"containers\": + [{\"volumeMounts\": [{\"mountPath\": \"/data\", \"name\": \"mypvc\"}], \"resources\": + {\"requests\": {\"cpu\": \"250m\"}, \"limits\": {\"cpu\": \"500m\"}}}], + \"serviceAccountName\": \"default-editor\", \"volumes\": [{\"name\": \"mypvc\", + \"persistentVolumeClaim\": {\"claimName\": \"my-awesome-kf-workshop-1703595962\"}}]}}"}'} + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: mnist-func + container: + args: [--log-folder, /data, '----output-paths', /tmp/outputs/logdir/data] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def mnist_func(log_folder):\n\n print('mnist_func:', log_folder)\n \ + \ import tensorflow as tf\n import json\n mnist = tf.keras.datasets.mnist\n\ + \ (x_train,y_train), (x_test, y_test) = mnist.load_data()\n x_train,\ + \ x_test = x_train/255.0, x_test/255.0\n\n def create_model():\n \ + \ return tf.keras.models.Sequential([\n tf.keras.layers.Flatten(input_shape\ + \ = (28,28)),\n tf.keras.layers.Dense(512, activation = 'relu'),\n\ + \ tf.keras.layers.Dropout(0.2),\n tf.keras.layers.Dense(10,\ + \ activation = 'softmax')\n ])\n model = create_model()\n model.compile(optimizer='adam',\n\ + \ loss='sparse_categorical_crossentropy',\n \ + \ metrics=['accuracy'])\n import datetime\n import os\n\n ###\ + \ add tensorboard logout callback\n log_dir = os.path.join(log_folder,\ + \ \"logs\", datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n tensorboard_callback\ + \ = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n \ + \ ######\n\n model.fit(x=x_train, \n y=y_train, \n \ + \ epochs=5, \n validation_data=(x_test, y_test), \n \ + \ callbacks=[tensorboard_callback])\n\n print('At least tensorboard\ + \ callbacks are correct')\n print('logdir:', log_dir)\n return ([log_dir])\n\ + \ndef _serialize_str(str_value: str) -> str:\n if not isinstance(str_value,\ + \ str):\n raise TypeError('Value \"{}\" has type \"{}\" instead of\ + \ str.'.format(\n str(str_value), str(type(str_value))))\n return\ + \ str_value\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Mnist\ + \ func', description='')\n_parser.add_argument(\"--log-folder\", dest=\"log_folder\"\ + , type=str, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"\ + ----output-paths\", dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args\ + \ = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"_output_paths\"\ + , [])\n\n_outputs = mnist_func(**_parsed_args)\n\n_output_serializers = [\n\ + \ _serialize_str,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow:2.0.0-py3 + resources: + limits: {cpu: '1'} + requests: {cpu: '1'} + volumeMounts: + - {mountPath: /data, name: mypvc} + inputs: + parameters: + - {name: mypvc-name} + outputs: + artifacts: + - {name: mnist-func-logdir, path: /tmp/outputs/logdir/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--log-folder", {"inputValue": "log_folder"}, "----output-paths", + {"outputPath": "logdir"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def mnist_func(log_folder):\n\n print(''mnist_func:'', log_folder)\n import + tensorflow as tf\n import json\n mnist = tf.keras.datasets.mnist\n (x_train,y_train), + (x_test, y_test) = mnist.load_data()\n x_train, x_test = x_train/255.0, + x_test/255.0\n\n def create_model():\n return tf.keras.models.Sequential([\n tf.keras.layers.Flatten(input_shape + = (28,28)),\n tf.keras.layers.Dense(512, activation = ''relu''),\n tf.keras.layers.Dropout(0.2),\n tf.keras.layers.Dense(10, + activation = ''softmax'')\n ])\n model = create_model()\n model.compile(optimizer=''adam'',\n loss=''sparse_categorical_crossentropy'',\n metrics=[''accuracy''])\n import + datetime\n import os\n\n ### add tensorboard logout callback\n log_dir + = os.path.join(log_folder, \"logs\", datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n tensorboard_callback + = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n ######\n\n model.fit(x=x_train, + \n y=y_train, \n epochs=5, \n validation_data=(x_test, + y_test), \n callbacks=[tensorboard_callback])\n\n print(''At + least tensorboard callbacks are correct'')\n print(''logdir:'', log_dir)\n return + ([log_dir])\n\ndef _serialize_str(str_value: str) -> str:\n if not isinstance(str_value, + str):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + str.''.format(\n str(str_value), str(type(str_value))))\n return + str_value\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Mnist + func'', description='''')\n_parser.add_argument(\"--log-folder\", dest=\"log_folder\", + type=str, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = mnist_func(**_parsed_args)\n\n_output_serializers + = [\n _serialize_str,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow:2.0.0-py3"}}, "inputs": [{"name": "log_folder", + "type": "String"}], "name": "Mnist func", "outputs": [{"name": "logdir", + "type": "String"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"log_folder": + "/data"}'} + volumes: + - name: mypvc + persistentVolumeClaim: {claimName: '{{inputs.parameters.mypvc-name}}'} + - name: mnist-pipeline + dag: + tasks: + - {name: create-tensorboard-visualization, template: create-tensorboard-visualization} + - name: mnist-func + template: mnist-func + dependencies: [create-tensorboard-visualization, mypvc] + arguments: + parameters: + - {name: mypvc-name, value: '{{tasks.mypvc.outputs.parameters.mypvc-name}}'} + - {name: mypvc, template: mypvc} + - name: mypvc + resource: + action: create + manifest: | + apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: '{{workflow.name}}-my-awesome-kf-workshop-1703595962' + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + outputs: + parameters: + - name: mypvc-manifest + valueFrom: {jsonPath: '{}'} + - name: mypvc-name + valueFrom: {jsonPath: '{.metadata.name}'} + - name: mypvc-size + valueFrom: {jsonPath: '{.status.capacity.storage}'} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + arguments: + parameters: [] + serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml new file mode 100644 index 000000000..b1a4a1e25 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml @@ -0,0 +1,131 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: only-decision-tree- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T21:42:00.682134', + pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Decision Tree + for classification problem.", "name": "only_decision_tree"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20} +spec: + entrypoint: only-decision-tree + templates: + - name: decision-tree-classifier + container: + args: [] + command: [python, decision_tree.py, --data, /tmp/inputs/Data/data, --accuracy, + /tmp/outputs/Accuracy/data] + image: lightnighttw/kubeflow:decision_tree_v2 + resources: + limits: + cpu: 2 + inputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/inputs/Data/data} + outputs: + parameters: + - name: decision-tree-classifier-Accuracy + valueFrom: {path: /tmp/outputs/Accuracy/data} + artifacts: + - {name: decision-tree-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains + a decision tree classifier", "implementation": {"container": {"command": + ["python", "decision_tree.py", "--data", {"inputPath": "Data"}, "--accuracy", + {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:decision_tree_v2"}}, + "inputs": [{"description": "Path where data is stored.", "name": "Data", + "type": "LocalPath"}], "name": "Decision Tree classifier", "outputs": [{"description": + "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "c5c232a9654213b3b222693949b71a5d561d04ed09543c20b6f8f2eab651ae0b", "url": + "decision_tree/decision_tree.yaml"}'} + - name: download-data-function + container: + args: [] + command: [python, download_data.py, --data, /tmp/outputs/Data/data] + image: lightnighttw/kubeflow:download_data + resources: + limits: + cpu: 2 + outputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/outputs/Data/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download + toy data from sklearn datasets", "implementation": {"container": {"command": + ["python", "download_data.py", "--data", {"outputPath": "Data"}], "image": + "lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function", + "outputs": [{"description": "Path where data will be stored.", "name": "Data", + "type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url": + "download_data/download_data.yaml"}'} + - name: only-decision-tree + dag: + tasks: + - name: decision-tree-classifier + template: decision-tree-classifier + dependencies: [download-data-function] + arguments: + artifacts: + - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} + - {name: download-data-function, template: download-data-function} + - name: show-results + template: show-results + dependencies: [decision-tree-classifier] + arguments: + parameters: + - {name: decision-tree-classifier-Accuracy, value: '{{tasks.decision-tree-classifier.outputs.parameters.decision-tree-classifier-Accuracy}}'} + - name: show-results + container: + args: [--decision-tree, '{{inputs.parameters.decision-tree-classifier-Accuracy}}'] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - | + def show_results(decision_tree): + # the results are shown. + + print(f"Decision tree (accuracy): {decision_tree}") + + import argparse + _parser = argparse.ArgumentParser(prog='Show results', description='') + _parser.add_argument("--decision-tree", dest="decision_tree", type=float, required=True, default=argparse.SUPPRESS) + _parsed_args = vars(_parser.parse_args()) + + _outputs = show_results(**_parsed_args) + image: python:3.7 + resources: + limits: + cpu: 2 + inputs: + parameters: + - {name: decision-tree-classifier-Accuracy} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--decision-tree", {"inputValue": "decision_tree"}], "command": + ["sh", "-ec", "program_path=$(mktemp)\nprintf \"%s\" \"$0\" > \"$program_path\"\npython3 + -u \"$program_path\" \"$@\"\n", "def show_results(decision_tree):\n # + the results are shown.\n\n print(f\"Decision tree (accuracy): {decision_tree}\")\n\nimport + argparse\n_parser = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--decision-tree\", + dest=\"decision_tree\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args + = vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"], + "image": "python:3.7"}}, "inputs": [{"name": "decision_tree", "type": "Float"}], + "name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"decision_tree": + "{{inputs.parameters.decision-tree-classifier-Accuracy}}"}'} + arguments: + parameters: [] + serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml new file mode 100644 index 000000000..2e10bcefa --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml @@ -0,0 +1,229 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: three-pipeline- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T12:05:44.365082', + pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Decision Tree, + random forest and Logistic Regression for classification problem.", "name": + "Three Pipeline"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} +spec: + entrypoint: three-pipeline + templates: + - name: decision-tree-classifier + container: + args: [] + command: [python, decision_tree.py, --data, /tmp/inputs/Data/data, --accuracy, + /tmp/outputs/Accuracy/data] + image: lightnighttw/kubeflow:decision_tree_v2 + resources: + limits: + cpu: 2 + inputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/inputs/Data/data} + outputs: + parameters: + - name: decision-tree-classifier-Accuracy + valueFrom: {path: /tmp/outputs/Accuracy/data} + artifacts: + - {name: decision-tree-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains + a decision tree classifier", "implementation": {"container": {"command": + ["python", "decision_tree.py", "--data", {"inputPath": "Data"}, "--accuracy", + {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:decision_tree_v2"}}, + "inputs": [{"description": "Path where data is stored.", "name": "Data", + "type": "LocalPath"}], "name": "Decision Tree classifier", "outputs": [{"description": + "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "c5c232a9654213b3b222693949b71a5d561d04ed09543c20b6f8f2eab651ae0b", "url": + "decision_tree/decision_tree.yaml"}'} + - name: download-data-function + container: + args: [] + command: [python, download_data.py, --data, /tmp/outputs/Data/data] + image: lightnighttw/kubeflow:download_data + resources: + limits: + cpu: 2 + outputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/outputs/Data/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download + toy data from sklearn datasets", "implementation": {"container": {"command": + ["python", "download_data.py", "--data", {"outputPath": "Data"}], "image": + "lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function", + "outputs": [{"description": "Path where data will be stored.", "name": "Data", + "type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url": + "download_data/download_data.yaml"}'} + - name: logistic-regression-classifier + container: + args: [] + command: [python, logistic_regression.py, --data, /tmp/inputs/Data/data, --accuracy, + /tmp/outputs/Accuracy/data] + image: lightnighttw/kubeflow:logistic_regression + resources: + limits: + cpu: 2 + inputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/inputs/Data/data} + outputs: + parameters: + - name: logistic-regression-classifier-Accuracy + valueFrom: {path: /tmp/outputs/Accuracy/data} + artifacts: + - {name: logistic-regression-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains + a Logistic Regression Classifier", "implementation": {"container": {"command": + ["python", "logistic_regression.py", "--data", {"inputPath": "Data"}, "--accuracy", + {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:logistic_regression"}}, + "inputs": [{"description": "Path where data is stored.", "name": "Data", + "type": "LocalPath"}], "name": "Logistic Regression Classifier", "outputs": + [{"description": "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', + pipelines.kubeflow.org/component_ref: '{"digest": "a8d1e77d07d18a75bef200aee96f35136833fc4bb535f33fd949a307beb094c2", + "url": "logistic_regression/logistic_regression.yaml"}'} + - name: random-forest-classifier + container: + args: [] + command: [python, randomforest.py, --data, /tmp/inputs/Data/data, --accuracy, + /tmp/outputs/Accuracy/data] + image: lightnighttw/kubeflow:random_forest_v4 + resources: + limits: + cpu: 2 + inputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/inputs/Data/data} + outputs: + parameters: + - name: random-forest-classifier-Accuracy + valueFrom: {path: /tmp/outputs/Accuracy/data} + artifacts: + - {name: random-forest-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Train + a random forest classifier", "implementation": {"container": {"command": + ["python", "randomforest.py", "--data", {"inputPath": "Data"}, "--accuracy", + {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:random_forest_v4"}}, + "inputs": [{"description": "Path where data is stored.", "name": "Data", + "type": "LocalPath"}], "name": "Random Forest classifier", "outputs": [{"description": + "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "b49b12da3371976eddf41d662685bb49d71b419d516de65efdd90938d2c706bc", "url": + "randomForest/random_forest.yaml"}'} + - name: show-results + container: + args: [--decision-tree, '{{inputs.parameters.decision-tree-classifier-Accuracy}}', + --logistic-regression, '{{inputs.parameters.logistic-regression-classifier-Accuracy}}', + --random-forest, '{{inputs.parameters.random-forest-classifier-Accuracy}}'] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - | + def show_results(decision_tree, logistic_regression, random_forest): + # Given the outputs from decision_tree and logistic regression components + # the results are shown. + + print(f"Decision tree (accuracy): {decision_tree}") + print(f"Logistic regression (accuracy): {logistic_regression}") + print(f"Random forest (accuracy): {random_forest}") + + import argparse + _parser = argparse.ArgumentParser(prog='Show results', description='') + _parser.add_argument("--decision-tree", dest="decision_tree", type=float, required=True, default=argparse.SUPPRESS) + _parser.add_argument("--logistic-regression", dest="logistic_regression", type=float, required=True, default=argparse.SUPPRESS) + _parser.add_argument("--random-forest", dest="random_forest", type=float, required=True, default=argparse.SUPPRESS) + _parsed_args = vars(_parser.parse_args()) + + _outputs = show_results(**_parsed_args) + image: python:3.7 + resources: + limits: + cpu: 2 + inputs: + parameters: + - {name: decision-tree-classifier-Accuracy} + - {name: logistic-regression-classifier-Accuracy} + - {name: random-forest-classifier-Accuracy} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--decision-tree", {"inputValue": "decision_tree"}, "--logistic-regression", + {"inputValue": "logistic_regression"}, "--random-forest", {"inputValue": + "random_forest"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def show_results(decision_tree, logistic_regression, random_forest):\n # + Given the outputs from decision_tree and logistic regression components\n # + the results are shown.\n\n print(f\"Decision tree (accuracy): {decision_tree}\")\n print(f\"Logistic + regression (accuracy): {logistic_regression}\")\n print(f\"Random forest + (accuracy): {random_forest}\")\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Show + results'', description='''')\n_parser.add_argument(\"--decision-tree\", + dest=\"decision_tree\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"--logistic-regression\", + dest=\"logistic_regression\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"--random-forest\", + dest=\"random_forest\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args + = vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"], + "image": "python:3.7"}}, "inputs": [{"name": "decision_tree", "type": "Float"}, + {"name": "logistic_regression", "type": "Float"}, {"name": "random_forest", + "type": "Float"}], "name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}', + pipelines.kubeflow.org/arguments.parameters: '{"decision_tree": "{{inputs.parameters.decision-tree-classifier-Accuracy}}", + "logistic_regression": "{{inputs.parameters.logistic-regression-classifier-Accuracy}}", + "random_forest": "{{inputs.parameters.random-forest-classifier-Accuracy}}"}'} + - name: three-pipeline + dag: + tasks: + - name: decision-tree-classifier + template: decision-tree-classifier + dependencies: [download-data-function] + arguments: + artifacts: + - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} + - {name: download-data-function, template: download-data-function} + - name: logistic-regression-classifier + template: logistic-regression-classifier + dependencies: [download-data-function] + arguments: + artifacts: + - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} + - name: random-forest-classifier + template: random-forest-classifier + dependencies: [download-data-function] + arguments: + artifacts: + - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} + - name: show-results + template: show-results + dependencies: [decision-tree-classifier, logistic-regression-classifier, random-forest-classifier] + arguments: + parameters: + - {name: decision-tree-classifier-Accuracy, value: '{{tasks.decision-tree-classifier.outputs.parameters.decision-tree-classifier-Accuracy}}'} + - {name: logistic-regression-classifier-Accuracy, value: '{{tasks.logistic-regression-classifier.outputs.parameters.logistic-regression-classifier-Accuracy}}'} + - {name: random-forest-classifier-Accuracy, value: '{{tasks.random-forest-classifier.outputs.parameters.random-forest-classifier-Accuracy}}'} + arguments: + parameters: [] + serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/requirements.txt b/kubeflow/examples/1.connect-kubeflow/py/requirements.txt new file mode 100644 index 000000000..0a8547bcc --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/py/requirements.txt @@ -0,0 +1,2 @@ +setuptools +wheel diff --git a/kubeflow/examples/1.connect-kubeflow/settings.js b/kubeflow/examples/1.connect-kubeflow/settings.js new file mode 100644 index 000000000..332013ee1 --- /dev/null +++ b/kubeflow/examples/1.connect-kubeflow/settings.js @@ -0,0 +1,498 @@ +/** + * This is the default settings file provided by Node-RED. + * + * It can contain any valid JavaScript code that will get run when Node-RED + * is started. + * + * Lines that start with // are commented out. + * Each entry should be separated from the entries above and below by a comma ',' + * + * For more information about individual settings, refer to the documentation: + * https://nodered.org/docs/user-guide/runtime/configuration + * + * The settings are split into the following sections: + * - Flow File and User Directory Settings + * - Security + * - Server Settings + * - Runtime Settings + * - Editor Settings + * - Node Settings + * + **/ + +module.exports = { + +/******************************************************************************* + * Flow File and User Directory Settings + * - flowFile + * - credentialSecret + * - flowFilePretty + * - userDir + * - nodesDir + ******************************************************************************/ + + /** The file containing the flows. If not set, defaults to flows_.json **/ + flowFile: 'flows.json', + + /** By default, credentials are encrypted in storage using a generated key. To + * specify your own secret, set the following property. + * If you want to disable encryption of credentials, set this property to false. + * Note: once you set this property, do not change it - doing so will prevent + * node-red from being able to decrypt your existing credentials and they will be + * lost. + */ + //credentialSecret: "a-secret-key", + credentialSecret: process.env.NODE_RED_CREDENTIAL_SECRET, + + /** By default, the flow JSON will be formatted over multiple lines making + * it easier to compare changes when using version control. + * To disable pretty-printing of the JSON set the following property to false. + */ + flowFilePretty: true, + + /** By default, all user data is stored in a directory called `.node-red` under + * the user's home directory. To use a different location, the following + * property can be used + */ + //userDir: '/home/nol/.node-red/', + + /** Node-RED scans the `nodes` directory in the userDir to find local node files. + * The following property can be used to specify an additional directory to scan. + */ + //nodesDir: '/home/nol/.node-red/nodes', + +/******************************************************************************* + * Security + * - adminAuth + * - https + * - httpsRefreshInterval + * - requireHttps + * - httpNodeAuth + * - httpStaticAuth + ******************************************************************************/ + + /** To password protect the Node-RED editor and admin API, the following + * property can be used. See http://nodered.org/docs/security.html for details. + */ + //adminAuth: { + // type: "credentials", + // users: [{ + // username: "admin", + // password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.", + // permissions: "*" + // }] + //}, + + /** The following property can be used to enable HTTPS + * This property can be either an object, containing both a (private) key + * and a (public) certificate, or a function that returns such an object. + * See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener + * for details of its contents. + */ + + /** Option 1: static object */ + //https: { + // key: require("fs").readFileSync('privkey.pem'), + // cert: require("fs").readFileSync('cert.pem') + //}, + + /** Option 2: function that returns the HTTP configuration object */ + // https: function() { + // // This function should return the options object, or a Promise + // // that resolves to the options object + // return { + // key: require("fs").readFileSync('privkey.pem'), + // cert: require("fs").readFileSync('cert.pem') + // } + // }, + + /** If the `https` setting is a function, the following setting can be used + * to set how often, in hours, the function will be called. That can be used + * to refresh any certificates. + */ + //httpsRefreshInterval : 12, + + /** The following property can be used to cause insecure HTTP connections to + * be redirected to HTTPS. + */ + //requireHttps: true, + + /** To password protect the node-defined HTTP endpoints (httpNodeRoot), + * including node-red-dashboard, or the static content (httpStatic), the + * following properties can be used. + * The `pass` field is a bcrypt hash of the password. + * See http://nodered.org/docs/security.html#generating-the-password-hash + */ + //httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + //httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + +/******************************************************************************* + * Server Settings + * - uiPort + * - uiHost + * - apiMaxLength + * - httpServerOptions + * - httpAdminRoot + * - httpAdminMiddleware + * - httpNodeRoot + * - httpNodeCors + * - httpNodeMiddleware + * - httpStatic + ******************************************************************************/ + + /** the tcp port that the Node-RED web server is listening on */ + uiPort: process.env.PORT || 1880, + + /** By default, the Node-RED UI accepts connections on all IPv4 interfaces. + * To listen on all IPv6 addresses, set uiHost to "::", + * The following property can be used to listen on a specific interface. For + * example, the following would only allow connections from the local machine. + */ + //uiHost: "127.0.0.1", + + /** The maximum size of HTTP request that will be accepted by the runtime api. + * Default: 5mb + */ + //apiMaxLength: '5mb', + + /** The following property can be used to pass custom options to the Express.js + * server used by Node-RED. For a full list of available options, refer + * to http://expressjs.com/en/api.html#app.settings.table + */ + //httpServerOptions: { }, + + /** By default, the Node-RED UI is available at http://localhost:1880/ + * The following property can be used to specify a different root path. + * If set to false, this is disabled. + */ + //httpAdminRoot: '/admin', + + /** The following property can be used to add a custom middleware function + * in front of all admin http routes. For example, to set custom http + * headers. It can be a single function or an array of middleware functions. + */ + // httpAdminMiddleware: function(req,res,next) { + // // Set the X-Frame-Options header to limit where the editor + // // can be embedded + // //res.set('X-Frame-Options', 'sameorigin'); + // next(); + // }, + + + /** Some nodes, such as HTTP In, can be used to listen for incoming http requests. + * By default, these are served relative to '/'. The following property + * can be used to specifiy a different root path. If set to false, this is + * disabled. + */ + //httpNodeRoot: '/red-nodes', + + /** The following property can be used to configure cross-origin resource sharing + * in the HTTP nodes. + * See https://github.com/troygoode/node-cors#configuration-options for + * details on its contents. The following is a basic permissive set of options: + */ + //httpNodeCors: { + // origin: "*", + // methods: "GET,PUT,POST,DELETE" + //}, + + /** If you need to set an http proxy please set an environment variable + * called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system. + * For example - http_proxy=http://myproxy.com:8080 + * (Setting it here will have no effect) + * You may also specify no_proxy (or NO_PROXY) to supply a comma separated + * list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk + */ + + /** The following property can be used to add a custom middleware function + * in front of all http in nodes. This allows custom authentication to be + * applied to all http in nodes, or any other sort of common request processing. + * It can be a single function or an array of middleware functions. + */ + //httpNodeMiddleware: function(req,res,next) { + // // Handle/reject the request, or pass it on to the http in node by calling next(); + // // Optionally skip our rawBodyParser by setting this to true; + // //req.skipRawBodyParser = true; + // next(); + //}, + + /** When httpAdminRoot is used to move the UI to a different root path, the + * following property can be used to identify a directory of static content + * that should be served at http://localhost:1880/. + */ + //httpStatic: '/home/nol/node-red-static/', + +/******************************************************************************* + * Runtime Settings + * - lang + * - logging + * - contextStorage + * - exportGlobalContextKeys + * - externalModules + ******************************************************************************/ + + /** Uncomment the following to run node-red in your preferred language. + * Available languages include: en-US (default), ja, de, zh-CN, zh-TW, ru, ko + * Some languages are more complete than others. + */ + // lang: "de", + + /** Configure the logging output */ + logging: { + /** Only console logging is currently supported */ + console: { + /** Level of logging to be recorded. Options are: + * fatal - only those errors which make the application unusable should be recorded + * error - record errors which are deemed fatal for a particular request + fatal errors + * warn - record problems which are non fatal + errors + fatal errors + * info - record information about the general running of the application + warn + error + fatal errors + * debug - record information which is more verbose than info + info + warn + error + fatal errors + * trace - record very detailed logging + debug + info + warn + error + fatal errors + * off - turn off all logging (doesn't affect metrics or audit) + */ + level: "info", + /** Whether or not to include metric events in the log output */ + metrics: false, + /** Whether or not to include audit events in the log output */ + audit: false + } + }, + + /** Context Storage + * The following property can be used to enable context storage. The configuration + * provided here will enable file-based context that flushes to disk every 30 seconds. + * Refer to the documentation for further options: https://nodered.org/docs/api/context/ + */ + //contextStorage: { + // default: { + // module:"localfilesystem" + // }, + //}, + + /** `global.keys()` returns a list of all properties set in global context. + * This allows them to be displayed in the Context Sidebar within the editor. + * In some circumstances it is not desirable to expose them to the editor. The + * following property can be used to hide any property set in `functionGlobalContext` + * from being list by `global.keys()`. + * By default, the property is set to false to avoid accidental exposure of + * their values. Setting this to true will cause the keys to be listed. + */ + exportGlobalContextKeys: false, + + /** Configure how the runtime will handle external npm modules. + * This covers: + * - whether the editor will allow new node modules to be installed + * - whether nodes, such as the Function node are allowed to have their + * own dynamically configured dependencies. + * The allow/denyList options can be used to limit what modules the runtime + * will install/load. It can use '*' as a wildcard that matches anything. + */ + externalModules: { + // autoInstall: false, /** Whether the runtime will attempt to automatically install missing modules */ + // autoInstallRetry: 30, /** Interval, in seconds, between reinstall attempts */ + // palette: { /** Configuration for the Palette Manager */ + // allowInstall: true, /** Enable the Palette Manager in the editor */ + // allowUpdate: true, /** Allow modules to be updated in the Palette Manager */ + // allowUpload: true, /** Allow module tgz files to be uploaded and installed */ + // allowList: ['*'], + // denyList: [], + // allowUpdateList: ['*'], + // denyUpdateList: [] + // }, + // modules: { /** Configuration for node-specified modules */ + // allowInstall: true, + // allowList: [], + // denyList: [] + // } + }, + + +/******************************************************************************* + * Editor Settings + * - disableEditor + * - editorTheme + ******************************************************************************/ + + /** The following property can be used to disable the editor. The admin API + * is not affected by this option. To disable both the editor and the admin + * API, use either the httpRoot or httpAdminRoot properties + */ + //disableEditor: false, + + /** Customising the editor + * See https://nodered.org/docs/user-guide/runtime/configuration#editor-themes + * for all available options. + */ + editorTheme: { + /** The following property can be used to set a custom theme for the editor. + * See https://github.com/node-red-contrib-themes/theme-collection for + * a collection of themes to chose from. + */ + //theme: "", + + /** To disable the 'Welcome to Node-RED' tour that is displayed the first + * time you access the editor for each release of Node-RED, set this to false + */ + //tours: false, + + palette: { + /** The following property can be used to order the categories in the editor + * palette. If a node's category is not in the list, the category will get + * added to the end of the palette. + * If not set, the following default order is used: + */ + //categories: ['subflows', 'common', 'function', 'network', 'sequence', 'parser', 'storage'], + }, + + projects: { + /** To enable the Projects feature, set this value to true */ + enabled: false, + workflow: { + /** Set the default projects workflow mode. + * - manual - you must manually commit changes + * - auto - changes are automatically committed + * This can be overridden per-user from the 'Git config' + * section of 'User Settings' within the editor + */ + mode: "manual" + } + }, + + codeEditor: { + /** Select the text editor component used by the editor. + * Defaults to "ace", but can be set to "ace" or "monaco" + */ + lib: "ace", + options: { + /** The follow options only apply if the editor is set to "monaco" + * + * theme - must match the file name of a theme in + * packages/node_modules/@node-red/editor-client/src/vendor/monaco/dist/theme + * e.g. "tomorrow-night", "upstream-sunburst", "github", "my-theme" + */ + theme: "vs", + /** other overrides can be set e.g. fontSize, fontFamily, fontLigatures etc. + * for the full list, see https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandaloneeditorconstructionoptions.html + */ + //fontSize: 14, + //fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace", + //fontLigatures: true, + } + } + }, + +/******************************************************************************* + * Node Settings + * - fileWorkingDirectory + * - functionGlobalContext + * - functionExternalModules + * - nodeMessageBufferMaxLength + * - ui (for use with Node-RED Dashboard) + * - debugUseColors + * - debugMaxLength + * - execMaxBufferSize + * - httpRequestTimeout + * - mqttReconnectTime + * - serialReconnectTime + * - socketReconnectTime + * - socketTimeout + * - tcpMsgQueueSize + * - inboundWebSocketTimeout + * - tlsConfigDisableLocalFiles + * - webSocketNodeVerifyClient + ******************************************************************************/ + + /** The working directory to handle relative file paths from within the File nodes + * defaults to the working directory of the Node-RED process. + */ + //fileWorkingDirectory: "", + + /** Allow the Function node to load additional npm modules directly */ + functionExternalModules: true, + + /** The following property can be used to set predefined values in Global Context. + * This allows extra node modules to be made available with in Function node. + * For example, the following: + * functionGlobalContext: { os:require('os') } + * will allow the `os` module to be accessed in a Function node using: + * global.get("os") + */ + functionGlobalContext: { + // os:require('os'), + }, + + /** The maximum number of messages nodes will buffer internally as part of their + * operation. This applies across a range of nodes that operate on message sequences. + * defaults to no limit. A value of 0 also means no limit is applied. + */ + //nodeMessageBufferMaxLength: 0, + + /** If you installed the optional node-red-dashboard you can set it's path + * relative to httpNodeRoot + * Other optional properties include + * readOnly:{boolean}, + * middleware:{function or array}, (req,res,next) - http middleware + * ioMiddleware:{function or array}, (socket,next) - socket.io middleware + */ + //ui: { path: "ui" }, + + /** Colourise the console output of the debug node */ + //debugUseColors: true, + + /** The maximum length, in characters, of any message sent to the debug sidebar tab */ + debugMaxLength: 1000, + + /** Maximum buffer size for the exec node. Defaults to 10Mb */ + //execMaxBufferSize: 10000000, + + /** Timeout in milliseconds for HTTP request connections. Defaults to 120s */ + //httpRequestTimeout: 120000, + + /** Retry time in milliseconds for MQTT connections */ + mqttReconnectTime: 15000, + + /** Retry time in milliseconds for Serial port connections */ + serialReconnectTime: 15000, + + /** Retry time in milliseconds for TCP socket connections */ + //socketReconnectTime: 10000, + + /** Timeout in milliseconds for TCP server socket connections. Defaults to no timeout */ + //socketTimeout: 120000, + + /** Maximum number of messages to wait in queue while attempting to connect to TCP socket + * defaults to 1000 + */ + //tcpMsgQueueSize: 2000, + + /** Timeout in milliseconds for inbound WebSocket connections that do not + * match any configured node. Defaults to 5000 + */ + //inboundWebSocketTimeout: 5000, + + /** To disable the option for using local files for storing keys and + * certificates in the TLS configuration node, set this to true. + */ + //tlsConfigDisableLocalFiles: true, + + /** The following property can be used to verify websocket connection attempts. + * This allows, for example, the HTTP request headers to be checked to ensure + * they include valid authentication information. + */ + //webSocketNodeVerifyClient: function(info) { + // /** 'info' has three properties: + // * - origin : the value in the Origin header + // * - req : the HTTP request + // * - secure : true if req.connection.authorized or req.connection.encrypted is set + // * + // * The function should return true if the connection should be accepted, false otherwise. + // * + // * Alternatively, if this function is defined to accept a second argument, callback, + // * it can be used to verify the client asynchronously. + // * The callback takes three arguments: + // * - result : boolean, whether to accept the connection or not + // * - code : if result is false, the HTTP error status to return + // * - reason: if result is false, the HTTP reason string to return + // */ + //}, +} diff --git a/kubeflow/examples/Dockerfile b/kubeflow/examples/Dockerfile new file mode 100644 index 000000000..f195a77fd --- /dev/null +++ b/kubeflow/examples/Dockerfile @@ -0,0 +1,20 @@ +FROM nodered/node-red:2.2.3-12 + +ARG PREFIX + +ENV NODE_OPTIONS=--max_old_space_size=128 + +USER root + +RUN apk update && \ + apk add py3-pip + +USER node-red +# Copy package.json to the WORKDIR so npm builds all +# of your added nodes modules for Node-RED +COPY package.json . +RUN npm install --unsafe-perm --no-update-notifier --no-fund --only=production + +ADD scripts/entrypoint.sh . + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/kubeflow/examples/README.md b/kubeflow/examples/README.md new file mode 100644 index 000000000..c56f4dd28 --- /dev/null +++ b/kubeflow/examples/README.md @@ -0,0 +1,40 @@ +#### Examples + +This example folder contains multiple node-red flow setups, each is isolated with a folder that allows you to run the different examples with the same settings. + +##### Add customized npm package + +You can add customized npm package via `npm install` or directly modify `packages.json`. Then rebuild your container image. + +##### Build + +Simply to run the following command to build node-red image + +``` +./build.sh +``` + +##### Run the container image + +To run the container image, use + +``` +KUBEFLOW_HOST= \ +KUBEFLOW_USERNAME= \ +KUBEFLOW_PASSWORD= \ +./run.sh +``` + +which would mount the current folder (i.e. ./example) onto the containers. We took this as a convenient step as you could change codes with node-red UI and the mounting volume allows the changes to be reflected onto your local file system. + +The example-args allows you to specify which example you want to run, for example + +``` +./run.sh 0.helloworld +``` + +would run the `0.helloworld` example. + +##### Visit vis UI + +then you can go to UI, check it out: http://127.0.0.1:1880/ diff --git a/kubeflow/examples/build.sh b/kubeflow/examples/build.sh new file mode 100644 index 000000000..37ad5136d --- /dev/null +++ b/kubeflow/examples/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +docker compose build diff --git a/kubeflow/examples/docker-compose.yaml b/kubeflow/examples/docker-compose.yaml new file mode 100644 index 000000000..2a9619477 --- /dev/null +++ b/kubeflow/examples/docker-compose.yaml @@ -0,0 +1,33 @@ +################################################################################ +# Node-RED Stack or Compose +################################################################################ +# docker stack deploy node-red --compose-file docker-compose-node-red.yml +# docker-compose -f docker-compose-node-red.yml -p myNoderedProject up +################################################################################ +version: "3.7" + +services: + node-red: + image: reg.footprint-ai.com/public/kube-nodered:latest + build: + context: . + dockerfile: Dockerfile + labels: + # workaround around a docker-compose bug when image is also used by docker run (https://github.com/docker/compose/issues/10162) + com.docker.compose.container-number: "1" + environment: + - TZ=Asia/Taipei + - USERDIR=$USERDIR + - NODE_RED_CREDENTIAL_SECRET=noderedtutorial + - KUBEFLOW_HOST=$KUBEFLOW_HOST + - KUBEFLOW_USERNAME=$KUBEFLOW_USERNAME + - KUBEFLOW_PASSWORD=$KUBEFLOW_PASSWORD + ports: + - "1880:1880" + networks: + - node-red-net + volumes: + - ./:/data + +networks: + node-red-net: diff --git a/kubeflow/examples/package-lock.json b/kubeflow/examples/package-lock.json new file mode 100644 index 000000000..a333a1615 --- /dev/null +++ b/kubeflow/examples/package-lock.json @@ -0,0 +1,10782 @@ +{ + "name": "node-red", + "version": "2.2.3", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "node-red", + "version": "2.2.3", + "license": "Apache-2.0", + "dependencies": { + "acorn": "8.7.0", + "acorn-walk": "8.2.0", + "ajv": "8.10.0", + "async-mutex": "0.3.2", + "basic-auth": "2.0.1", + "bcryptjs": "2.4.3", + "body-parser": "1.19.1", + "cheerio": "1.0.0-rc.10", + "clone": "2.1.2", + "content-type": "1.0.4", + "cookie": "0.4.2", + "cookie-parser": "1.4.6", + "cors": "2.8.5", + "cronosjs": "1.7.1", + "denque": "2.0.1", + "express": "4.17.2", + "express-session": "1.17.2", + "form-data": "4.0.0", + "fs-extra": "10.0.0", + "fs.notify": "0.0.4", + "got": "11.8.3", + "hash-sum": "2.0.0", + "hpagent": "0.1.2", + "https-proxy-agent": "5.0.0", + "i18next": "21.6.11", + "iconv-lite": "0.6.3", + "is-utf8": "0.2.1", + "js-yaml": "3.14.1", + "json-stringify-safe": "5.0.1", + "jsonata": "1.8.6", + "lodash.clonedeep": "^4.5.0", + "media-typer": "1.1.0", + "memorystore": "1.6.7", + "mime": "3.0.0", + "moment-timezone": "0.5.34", + "mqtt": "4.3.5", + "multer": "1.4.4", + "mustache": "4.2.0", + "node-red": "2.2.3", + "node-red-admin": "^2.2.3", + "node-red-contrib-pythonshell": "github:namgk/node-red-contrib-pythonshell", + "nopt": "5.0.0", + "oauth2orize": "1.11.1", + "on-headers": "1.0.2", + "passport": "0.5.2", + "passport-http-bearer": "1.0.1", + "passport-oauth2-client-password": "0.1.2", + "raw-body": "2.4.3", + "semver": "7.3.5", + "tar": "6.1.11", + "tough-cookie": "4.0.0", + "uglify-js": "3.15.1", + "uuid": "8.3.2", + "ws": "7.5.6", + "xml2js": "0.4.23" + }, + "devDependencies": { + "dompurify": "2.3.6", + "grunt": "1.5.2", + "grunt-chmod": "~1.1.1", + "grunt-cli": "~1.4.3", + "grunt-concurrent": "3.0.0", + "grunt-contrib-clean": "~2.0.0", + "grunt-contrib-compress": "2.0.0", + "grunt-contrib-concat": "~1.0.1", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-jshint": "3.1.1", + "grunt-contrib-uglify": "5.0.1", + "grunt-contrib-watch": "~1.1.0", + "grunt-jsdoc": "2.4.1", + "grunt-jsdoc-to-markdown": "6.0.0", + "grunt-jsonlint": "2.1.3", + "grunt-mkdir": "~1.1.0", + "grunt-npm-command": "~0.1.2", + "grunt-sass": "~3.1.0", + "grunt-simple-mocha": "~0.4.1", + "grunt-simple-nyc": "^3.0.1", + "i18next-http-backend": "1.3.2", + "jquery-i18next": "1.2.1", + "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", + "marked": "4.0.12", + "minami": "1.2.3", + "mocha": "9.2.0", + "node-red-node-test-helper": "^0.2.7", + "nodemon": "2.0.15", + "proxy": "^1.0.2", + "sass": "1.49.7", + "should": "13.2.3", + "sinon": "11.1.2", + "stoppable": "^1.1.0", + "supertest": "6.2.2" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", + "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", + "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.3", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.3", + "@babel/types": "^7.21.3", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", + "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@jsdoc/salty": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", + "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@node-red/editor-api": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-2.2.3.tgz", + "integrity": "sha512-lSqxKyf5FfODGCPQoJVr3m6oHxwIWhOQ6q1fIIxkL5JGQLJ3X/F5Du/hkgNUIr5W670S+WW+rYdx109ifiz1ng==", + "dependencies": { + "@node-red/editor-client": "2.2.3", + "@node-red/util": "2.2.3", + "bcryptjs": "2.4.3", + "body-parser": "1.19.1", + "clone": "2.1.2", + "cors": "2.8.5", + "express": "4.17.2", + "express-session": "1.17.2", + "memorystore": "1.6.7", + "mime": "3.0.0", + "multer": "1.4.4", + "mustache": "4.2.0", + "oauth2orize": "1.11.1", + "passport": "0.5.2", + "passport-http-bearer": "1.0.1", + "passport-oauth2-client-password": "0.1.2", + "ws": "7.5.6" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + } + }, + "node_modules/@node-red/editor-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-2.2.3.tgz", + "integrity": "sha512-rkxx1VDE4IRiWj9u1f3yxdrt4JUP4mBtPLaLOZfPn7gPvXPJAmzA6MTzeetLWFAopxUCuH4+xsrfl5sOh1RFwQ==" + }, + "node_modules/@node-red/nodes": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-2.2.3.tgz", + "integrity": "sha512-LRaoYQgWYGT3vDfHV+xHi33w7n9KDbNe9u77mNkLAna/PHq2IVViFWtBLm4uxhrYMYs7NNr7r+3NnVyhLGQlAQ==", + "dependencies": { + "acorn": "8.7.0", + "acorn-walk": "8.2.0", + "ajv": "8.10.0", + "body-parser": "1.19.1", + "cheerio": "1.0.0-rc.10", + "content-type": "1.0.4", + "cookie": "0.4.2", + "cookie-parser": "1.4.6", + "cors": "2.8.5", + "cronosjs": "1.7.1", + "denque": "2.0.1", + "form-data": "4.0.0", + "fs-extra": "10.0.0", + "fs.notify": "0.0.4", + "got": "11.8.3", + "hash-sum": "2.0.0", + "hpagent": "0.1.2", + "https-proxy-agent": "5.0.0", + "iconv-lite": "0.6.3", + "is-utf8": "0.2.1", + "js-yaml": "3.14.1", + "media-typer": "1.1.0", + "mqtt": "4.3.5", + "multer": "1.4.4", + "mustache": "4.2.0", + "on-headers": "1.0.2", + "raw-body": "2.4.3", + "tough-cookie": "4.0.0", + "uuid": "8.3.2", + "ws": "7.5.6", + "xml2js": "0.4.23" + } + }, + "node_modules/@node-red/registry": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-2.2.3.tgz", + "integrity": "sha512-fR//QJhqDGfq91lg9onknb13xhTXMCSTQRdR1FbvhgR5g0uS4fl7ZcKTBhWkp7OzUZ+pRInuuc6JeBZTaeLKQg==", + "dependencies": { + "@node-red/util": "2.2.3", + "clone": "2.1.2", + "fs-extra": "10.0.0", + "semver": "7.3.5", + "tar": "6.1.11", + "uglify-js": "3.15.1" + } + }, + "node_modules/@node-red/runtime": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-2.2.3.tgz", + "integrity": "sha512-NQrrhpg4daIdxkqET4n20az1sV5V5OvSpfkemKZbuXuicrPy4sGZ1OZ309v4QVbky97RgVrs7iv2Z1IRBXV8og==", + "dependencies": { + "@node-red/registry": "2.2.3", + "@node-red/util": "2.2.3", + "async-mutex": "0.3.2", + "clone": "2.1.2", + "express": "4.17.2", + "fs-extra": "10.0.0", + "json-stringify-safe": "5.0.1" + } + }, + "node_modules/@node-red/util": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/util/-/util-2.2.3.tgz", + "integrity": "sha512-N/3US+wwa3mVm3jkSV/QPfVIRdQjaXyChgRPm9UAZbls6TrxJFfZxZefQt4xNKoDYQkHoFNN65Q29RtV0GfbbA==", + "dependencies": { + "fs-extra": "10.0.0", + "i18next": "21.6.11", + "json-stringify-safe": "5.0.1", + "jsonata": "1.8.6", + "lodash.clonedeep": "^4.5.0", + "moment-timezone": "0.5.34" + } + }, + "node_modules/@prantlf/jsonlint": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@prantlf/jsonlint/-/jsonlint-10.2.0.tgz", + "integrity": "sha512-KMFfds0peWLLfCu3bhClTiEN0tdj/Z86QJvn1awKHws6r+Sx6T3a44Eadz6OvqN6ZpsRkqaRpZxqddvvDAdDZQ==", + "dev": true, + "dependencies": { + "ajv": "6.10.2", + "commander": "4.0.1" + }, + "bin": { + "jsonlint": "lib/cli.js" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@prantlf/jsonlint/node_modules/ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/@prantlf/jsonlint/node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "dev": true + }, + "node_modules/@prantlf/jsonlint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", + "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.15.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", + "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/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/agent-base/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/ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escape-sequences": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", + "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ansi-escape-sequences/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "dependencies": { + "default-require-extensions": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true + }, + "node_modules/archiver": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/archiver/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/args": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz", + "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==", + "dev": true, + "dependencies": { + "camelcase": "5.0.0", + "chalk": "2.4.2", + "leven": "2.1.0", + "mri": "1.1.4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/args/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/args/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/args/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/args/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/args/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/args/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/args/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "node_modules/async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha512-2tEzliJmf5fHNafNwQLJXUasGzQCVctvsNkXmnlELHwypU0p08/rHohYvkqKIjyXpx+0rkrYv6QbhJ+UF4QkBg==", + "engines": { + "node": "*" + } + }, + "node_modules/async-mutex": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", + "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.0.tgz", + "integrity": "sha512-XV/WrPxXfzgZ8j4lcB5i6LyaXmi90yetmV/Fem0kmglGx+mpY06CiweL3YxU6wOTNLmqLUePW4G8h45nGZ/+pA==", + "deprecated": "Formdata complete broken, incorrect build size", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "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/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth-parser": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/basic-auth-parser/-/basic-auth-parser-0.0.2.tgz", + "integrity": "sha512-Y7OBvWn+JnW45JWHLY6ybYub2k9cXCMrtCyO1Hds2s6eqClqWhPnOQpgXUPjAiMHj+A8TEPIQQ1dYENnJoBOHQ==", + "dev": true + }, + "node_modules/bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ==", + "dev": true, + "dependencies": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } + }, + "node_modules/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "dependencies": { + "bytes": "3.1.1", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "dependencies": { + "bytes": "3.1.1", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body/node_modules/bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==", + "dev": true + }, + "node_modules/body/node_modules/raw-body": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==", + "dev": true, + "dependencies": { + "bytes": "1", + "string_decoder": "0.10" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/body/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==", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/busboy/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/busboy/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/busboy/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/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cache-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", + "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", + "dev": true, + "dependencies": { + "array-back": "^4.0.1", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cache-point/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "dev": true, + "dependencies": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/caching-transform/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/caching-transform/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dependencies": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", + "dependencies": { + "css-select": "^4.3.0", + "css-what": "^6.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.3.1", + "domutils": "^2.8.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", + "dev": true, + "dependencies": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "engines": { + "node": ">=0.2.5" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/cli-table/node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/collect-all": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", + "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", + "dev": true, + "dependencies": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-args/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/command-line-args/node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-tool/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commander": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.0.1.tgz", + "integrity": "sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/common-sequence": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", + "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dev": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha512-n7LBL1zBzYdTpF1mx5DNcZnZn05CWIdsdvtPL4MosvqbBUK3Rq6VWEtGUuF3Y0s9/CIhMejezqlSkP6TnCJ/9g==", + "dev": true, + "dependencies": { + "walk-back": "^2.0.1" + } + }, + "node_modules/config-master/node_modules/walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha512-Nb6GvBR8UWX1D+Le+xUq0+Q1kFmRBIWVrfLnQAOmcpEzA9oAxwJ9gIr36t9TWYfzvWRvuMtjHiVsJYEkXWaTAQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/configstore/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", + "dev": true, + "dependencies": { + "date-now": "^0.1.4" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/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/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/continuable-cache": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "integrity": "sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "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/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cp-file/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cp-file/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cronosjs": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/cronosjs/-/cronosjs-1.7.1.tgz", + "integrity": "sha512-d6S6+ep7dJxsAG8OQQCdKuByI/S/AV64d9OF5mtmcykOyPu92cAkAnF3Tbc9s5oOaLQBYYQmTNvjqYRkPJ/u5Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==", + "dev": true + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "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/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha512-B0n2zDIXpzLzKeoEozorDSa1cHc1t0NjmxP0zuAxbizNU2MBqYJJKYXrrFdKuQliojXynrxgd7l4ahfg/+aA5g==", + "dev": true, + "dependencies": { + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true + }, + "node_modules/denque": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", + "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dicer/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/dicer/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/dicer/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/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dmd": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.2.0.tgz", + "integrity": "sha512-uXWxLF1H7TkUAuoHK59/h/ts5cKavm2LnhrIgJWisip4BVzPoXavlwyoprFFn2CzcahKYgvkfaebS6oxzgflkg==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "common-sequence": "^2.0.2", + "file-set": "^4.0.2", + "handlebars": "^4.7.7", + "marked": "^4.2.3", + "object-get": "^2.1.1", + "reduce-flatten": "^3.0.1", + "reduce-unique": "^2.0.1", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^5.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmd/node_modules/marked": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", + "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz", + "integrity": "sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==", + "dev": true + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "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==", + "devOptional": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", + "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", + "dev": true, + "dependencies": { + "string-template": "~0.2.1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==", + "dev": true + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", + "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.6", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-session": { + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", + "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express-session/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/express/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/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/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha512-Xhj93RXbMSq8urNCUq4p9l0P6hnySJ/7YNRhYNug0bLOuii7pKO7xQFb5mx9xZXWCar88pLPb805PvUkwrLZpQ==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-set": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", + "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", + "dev": true, + "dependencies": { + "array-back": "^5.0.0", + "glob": "^7.1.6" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/file-set/node_modules/array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/file-sync-cmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", + "integrity": "sha512-0k45oWBokCqh2MOexeYKpyqmGKG+8mQ2Wd8iawx+uWd/weWJQAZ6SoPybagdCI4xFisag8iAR77WPm4h3pTfxA==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha512-z8Nrwhi6wzxNMIbxlrTzuUW6KWuKkogZ/7OdDVq+0+kxn77KUH1nipx8iU6suqkHqc4y6n7a9A8IpmxY/pTjWg==", + "dev": true, + "dependencies": { + "glob": "~5.0.0" + }, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/findup-sync/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "dev": true, + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha512-3TOY+4TKV0Ml83PXJQY+JFQaHNV38lzQDIzzXYg1kWdBLenGgoZhAs0CKgzI31vi2pWEpQMq/Yi4bpKwCPkw7g==", + "dev": true, + "dependencies": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "node_modules/foreground-child/node_modules/cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA==", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/foreground-child/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.1.tgz", + "integrity": "sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==", + "dev": true, + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/formidable/node_modules/qs": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", + "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha512-X712jAOaWXkemQCAmWeg5rOT2i+KOpWz1Z/txk/cW0qlOu2oQ9H61vc5w3X/iyuUEfq/OyaFJ78/cZAQD1/bgA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fs.notify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fs.notify/-/fs.notify-0.0.4.tgz", + "integrity": "sha512-xnulkRf31FQwC8NsU5DEYqMTeM3jZpYsTC2hHQcHlkXTubxQHDVWkau13U/oFmFXieCkai2oKTa1MhckXk2fRQ==", + "dependencies": { + "async": "~0.1.22", + "retry": "~0.6.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "dependencies": { + "globule": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getobject": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz", + "integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globule": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", + "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", + "dev": true, + "dependencies": { + "glob": "~7.1.1", + "lodash": "^4.17.21", + "minimatch": "~3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/got": { + "version": "11.8.3", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", + "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/grunt": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.5.2.tgz", + "integrity": "sha512-XCtfaIu72OyDqK24MjWiGC9SwlkuhkS1mrULr1xzuJ2XqAFhP3ZAchZGHJeSCY6mkaOXU4F7SbmmCF7xIVoC9w==", + "dev": true, + "dependencies": { + "dateformat": "~3.0.3", + "eventemitter2": "~0.4.13", + "exit": "~0.1.2", + "findup-sync": "~0.3.0", + "glob": "~7.1.6", + "grunt-cli": "~1.4.3", + "grunt-known-options": "~2.0.0", + "grunt-legacy-log": "~3.0.0", + "grunt-legacy-util": "~2.0.1", + "iconv-lite": "~0.4.13", + "js-yaml": "~3.14.0", + "minimatch": "~3.0.4", + "mkdirp": "~1.0.4", + "nopt": "~3.0.6", + "rimraf": "~3.0.2" + }, + "bin": { + "grunt": "bin/grunt" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/grunt-chmod": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-chmod/-/grunt-chmod-1.1.1.tgz", + "integrity": "sha512-f807W/VOIhhaOW85JyeRd4DgB0RcbsGQV/4IvtcKctOWGvPJns4AqN7xW73PG9+RwDnSGxApS+6Xov5L2LeNXg==", + "dev": true, + "dependencies": { + "shelljs": "^0.5.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/grunt-cli": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", + "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", + "dev": true, + "dependencies": { + "grunt-known-options": "~2.0.0", + "interpret": "~1.1.0", + "liftup": "~3.0.1", + "nopt": "~4.0.1", + "v8flags": "~3.2.0" + }, + "bin": { + "grunt": "bin/grunt" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-cli/node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/grunt-concurrent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-concurrent/-/grunt-concurrent-3.0.0.tgz", + "integrity": "sha512-AgXtjUJESHEGeGX8neL3nmXBTHSj1QC48ABQ3ng2/vjuSBpDD8gKcVHSlXP71pFkIR8TQHf+eomOx6OSYSgfrA==", + "dev": true, + "dependencies": { + "arrify": "^2.0.1", + "async": "^3.1.0", + "indent-string": "^4.0.0", + "pad-stream": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "grunt": ">=1" + } + }, + "node_modules/grunt-concurrent/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/grunt-contrib-clean": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-2.0.1.tgz", + "integrity": "sha512-uRvnXfhiZt8akb/ZRDHJpQQtkkVkqc/opWO4Po/9ehC2hPxgptB9S6JHDC/Nxswo4CJSM0iFPT/Iym3cEMWzKA==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "rimraf": "^2.6.2" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "grunt": ">=0.4.5" + } + }, + "node_modules/grunt-contrib-clean/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/grunt-contrib-clean/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/grunt-contrib-compress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-2.0.0.tgz", + "integrity": "sha512-r/dAGx4qG+rmBFF4lb/hTktW2huGMGxkSLf9msh3PPtq0+cdQRQerZJ30UKevX3BLQsohwLzO0p1z/LrH6aKXQ==", + "dev": true, + "dependencies": { + "adm-zip": "^0.5.1", + "archiver": "^5.1.0", + "chalk": "^4.1.0", + "lodash": "^4.17.20", + "pretty-bytes": "^5.4.1", + "stream-buffers": "^3.0.2" + }, + "engines": { + "node": ">=10.16" + } + }, + "node_modules/grunt-contrib-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz", + "integrity": "sha512-QdTmcxe8aim2Z0dFeuSJ+f7fHIeY7PZaTMZxgvosjXwyMhpy2GUR5WHkr12lksHfZVE80v2wUwqF56wyfPUwoQ==", + "dev": true, + "dependencies": { + "chalk": "^1.0.0", + "source-map": "^0.5.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "grunt": ">=0.4.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-copy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", + "integrity": "sha512-gFRFUB0ZbLcjKb67Magz1yOHGBkyU6uL29hiEW1tdQ9gQt72NuMKIy/kS6dsCbV0cZ0maNCb0s6y+uT1FKU7jA==", + "dev": true, + "dependencies": { + "chalk": "^1.1.1", + "file-sync-cmp": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-jshint": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-3.1.1.tgz", + "integrity": "sha512-EwMY6L91FqTcMlZTVoDeeq/EZL+7MoFyo1rxIea9sxyv73geVggeE37jcUhNbu5hLbxHE82CGIUqitHuR2/q+g==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "hooker": "^0.2.3", + "jshint": "~2.13.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-contrib-uglify": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-5.0.1.tgz", + "integrity": "sha512-T/aXZ4WIpAtoswZqb6HROKg7uq9QbKwl+lUuOwK4eoFj3tFv9/a/oMyd3/qvetV29Pbf8P1YYda1gDwZppr60A==", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "maxmin": "^2.1.0", + "uglify-js": "^3.13.3", + "uri-path": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/grunt-contrib-uglify/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-watch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", + "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", + "dev": true, + "dependencies": { + "async": "^2.6.0", + "gaze": "^1.1.0", + "lodash": "^4.17.10", + "tiny-lr": "^1.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-watch/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/grunt-jsdoc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz", + "integrity": "sha512-S0zxU0wDewRu7z+vijEItOWe/UttxWVmvz0qz2ZVcAYR2GpXjsiski2CAVN0b18t2qeVLdmxZkJaEWCOsKzcAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1", + "jsdoc": "^3.6.3" + }, + "bin": { + "grunt-jsdoc": "bin/grunt-jsdoc" + }, + "engines": { + "node": ">= 8.12.0" + } + }, + "node_modules/grunt-jsdoc-to-markdown": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/grunt-jsdoc-to-markdown/-/grunt-jsdoc-to-markdown-6.0.0.tgz", + "integrity": "sha512-vvanKUErp6CHl4MuLQ9vwJewpMu8Fi7z09lr4OwMLr+GBu3nG5lRNZuu5mkWY8qv1aU8WkX97/rJaVs3A1Wx8g==", + "dev": true, + "dependencies": { + "jsdoc-to-markdown": "^7.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "grunt": ">=1.3.0" + } + }, + "node_modules/grunt-jsonlint": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/grunt-jsonlint/-/grunt-jsonlint-2.1.3.tgz", + "integrity": "sha512-h04qC969LIyhsJaASeJ/hDnnKnsnSNZKqjYHra6cc/WQzrfMZinQPdr11FhU4T8OzAq6ecMX5QauYiJkbjUV/Q==", + "dev": true, + "dependencies": { + "@prantlf/jsonlint": "10.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/grunt-known-options": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", + "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-legacy-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", + "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", + "dev": true, + "dependencies": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.19" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/grunt-legacy-log-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", + "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", + "dev": true, + "dependencies": { + "chalk": "~4.1.0", + "lodash": "~4.17.19" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-legacy-util": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", + "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", + "dev": true, + "dependencies": { + "async": "~3.2.0", + "exit": "~0.1.2", + "getobject": "~1.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.21", + "underscore.string": "~3.3.5", + "which": "~2.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-legacy-util/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/grunt-mkdir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-mkdir/-/grunt-mkdir-1.1.0.tgz", + "integrity": "sha512-FRE17OYVveNbVJFX8GPGa5bzH2ZiAdBx3q0Kwk2Dg6l+TzLGaTdufUxiUWUbS2MERFacnmXZwDDOR5ZbYW0o+Q==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + }, + "peerDependencies": { + "grunt": ">=0.4.0" + } + }, + "node_modules/grunt-npm-command": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/grunt-npm-command/-/grunt-npm-command-0.1.2.tgz", + "integrity": "sha512-QsGLL8Pp+tzeIkCqohIbOtVopOhINErRVpxKY+SnvSEE3BXOKKSanlIh9cd1mliajO57sXG2ZC4R8L3v2NSPTQ==", + "dev": true, + "peerDependencies": { + "grunt": ">=0.4.0" + } + }, + "node_modules/grunt-sass": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.1.0.tgz", + "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", + "dev": true, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "grunt": ">=1" + } + }, + "node_modules/grunt-simple-mocha": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/grunt-simple-mocha/-/grunt-simple-mocha-0.4.1.tgz", + "integrity": "sha512-EibTuZVvyLd9v/9An+5sL+XLoArs1QkFSTUcOG/AbBzeCYemZppcO9YSEspWUwU/T/NNtAyzB+x7B6zAmKQqkA==", + "dev": true, + "dependencies": { + "mocha": "*" + }, + "bin": { + "grunt-simple-mocha": "bin/grunt-simple-mocha" + }, + "engines": { + "node": "*" + } + }, + "node_modules/grunt-simple-nyc": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/grunt-simple-nyc/-/grunt-simple-nyc-3.0.1.tgz", + "integrity": "sha512-/YLY+jNI6gBuVO3xu07zwvDN+orTAFS50W00yb/2ncvc2PFO4pR+oU7TyiHhe8a6O3KuQDHsyCE0iE+rqJagQg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15", + "nyc": "^14.1.0", + "simple-cli": "^5.0.3" + } + }, + "node_modules/grunt/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt/node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/gzip-size": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", + "integrity": "sha512-6s8trQiK+OMzSaCSVXX+iqIcLV9tC+E73jrJrJTyS4h/AJhlxHvzFKqM1YLDJWRGgHX8uLkBeXkA0njNj39L4w==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.1" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + }, + "node_modules/hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha512-w0Kz8lJFBoyaurBiNrIvxPqr/gJ6fOfSkpAPOepN3oECqGJag37xPbOv57izi/KP8auHgNYxn5fXtAb+1LsJ6w==", + "dev": true, + "dependencies": { + "is-stream": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha512-t+UerCsQviSymAInD01Pw+Dn/usmz1sRO+3Zk1+lx8eg+WKpD2ulcwWqHHL0+aseRBr+3+vIhiG1K1JTwaIcTA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/hpagent": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-0.1.2.tgz", + "integrity": "sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/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/https-proxy-agent/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/i18next": { + "version": "21.6.11", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.11.tgz", + "integrity": "sha512-tJ2+o0lVO+fhi8bPkCpBAeY1SgkqmQm5NzgPWCQssBrywJw98/o+Kombhty5nxQOpHtvMmsxcOopczUiH6bJxQ==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/i18next-http-backend": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.3.2.tgz", + "integrity": "sha512-SfcoUmsSWnc2LYsDsCq5TCg18cxJXvXymX9N37V+qqMKQY8Gf0rWkjOnRd20sMK633Dq4NF9tvqPbOiFJ49Kbw==", + "dev": true, + "dependencies": { + "cross-fetch": "3.1.5" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/immutable": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", + "dev": true + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha512-CLM8SNMDu7C5psFCn6Wg/tgpj/bKAg7hc2gWqcuR9OD5Ft9PhBpIu8PLicPeis+xDd6YX2ncI8MCA64I9tftIA==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "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/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "dev": true, + "dependencies": { + "append-transform": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/istanbul-lib-source-maps/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jquery-i18next": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jquery-i18next/-/jquery-i18next-1.2.1.tgz", + "integrity": "sha512-UNcw3rgxoKjGEg4w23FEn2h3OlPJU7rPzsgDuXDBZktIzeiVbJohs9Cv9hj8oP8KNfBRKOoErL/OVxg2FaAR4g==", + "dev": true + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", + "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.4", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc-api": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.2.0.tgz", + "integrity": "sha512-93YDnlm/OYTlLOFeNs4qAv0RBCJ0kGj67xQaWy8wrbk97Rw1EySitoOTHsTHXPEs3uyx2IStPKGrbE7LTnZXbA==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "collect-all": "^1.0.4", + "file-set": "^4.0.2", + "fs-then-native": "^2.0.0", + "jsdoc": "^4.0.0", + "object-to-spawn-args": "^2.0.1", + "temp-path": "^1.0.0", + "walk-back": "^5.1.0" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/jsdoc-api/node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc-nr-template": { + "version": "1.0.0", + "resolved": "git+ssh://git@github.com/node-red/jsdoc-nr-template.git#3c7c8f96d585c7c5918a2e63519310e1297e162d", + "dev": true + }, + "node_modules/jsdoc-parse": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.2.0.tgz", + "integrity": "sha512-Afu1fQBEb7QHt6QWX/6eUWvYHJofB90Fjx7FuJYF7mnG9z5BkAIpms1wsnvYLytfmqpEENHs/fax9p8gvMj7dw==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "reduce-extract": "^1.0.0", + "sort-array": "^4.1.5", + "test-value": "^3.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdoc-to-markdown": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", + "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^6.1.0", + "jsdoc-api": "^7.1.1", + "jsdoc-parse": "^6.1.0", + "walk-back": "^5.1.0" + }, + "bin": { + "jsdoc2md": "bin/cli.js" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jshint": { + "version": "2.13.6", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.6.tgz", + "integrity": "sha512-IVdB4G0NTTeQZrBoM8C5JFVLjV2KtZ9APgybDA1MK73xb09qFs0jCXyQLnCOp1cSZZZbvhq/6mfXHUTaDkffuQ==", + "dev": true, + "dependencies": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "strip-json-comments": "1.0.x" + }, + "bin": { + "jshint": "bin/jshint" + } + }, + "node_modules/jshint/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/jshint/node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/jshint/node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jshint/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "node_modules/jshint/node_modules/domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", + "dev": true, + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/jshint/node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/jshint/node_modules/entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==", + "dev": true + }, + "node_modules/jshint/node_modules/htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", + "dev": true, + "dependencies": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "node_modules/jshint/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==", + "dev": true + }, + "node_modules/jshint/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==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/jshint/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==", + "dev": true + }, + "node_modules/jshint/node_modules/strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", + "dev": true, + "bin": { + "strip-json-comments": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/jsonata": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-1.8.6.tgz", + "integrity": "sha512-ZH2TPYdNP2JecOl/HvrH47Xc+9imibEMQ4YqKy/F/FrM+2a6vfbGxeCX23dB9Fr6uvGwv+ghf1KxWB3iZk09wA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "node_modules/key-list": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/key-list/-/key-list-0.1.4.tgz", + "integrity": "sha512-DMGLZAmEoKRUHPlc772EW0i92P/WY12/oWYc2pQZb5MVGOSjYmF0BEQXbOLjbou1+/PqZ+CivwfyjaUwmyl4CQ==", + "dev": true + }, + "node_modules/keyv": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/liftup": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", + "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", + "dev": true, + "dependencies": { + "extend": "^3.0.2", + "findup-sync": "^4.0.0", + "fined": "^1.2.0", + "flagged-respawn": "^1.0.1", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.1", + "rechoir": "^0.7.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/liftup/node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/livereload-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", + "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", + "dev": true + }, + "node_modules/lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==", + "dev": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "dev": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "devOptional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "devOptional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/maxmin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", + "integrity": "sha512-NWlApBjW9az9qRPaeg7CX4sQBWwytqz32bIEo1PW9pRW+kBP9KLRfJO3UC+TV31EcQZEUq7eMzikC7zt3zPJcw==", + "dev": true, + "dependencies": { + "chalk": "^1.0.0", + "figures": "^1.0.1", + "gzip-size": "^3.0.0", + "pretty-bytes": "^3.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/maxmin/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/maxmin/node_modules/pretty-bytes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", + "integrity": "sha512-eb7ZAeUTgfh294cElcu51w+OTRp/6ItW758LjwJSK72LDevcuJn0P4eD71PLMDGPwwatXmAmYHTkzvpKlJE3ow==", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/memorystore": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/memorystore/-/memorystore-1.6.7.tgz", + "integrity": "sha512-OZnmNY/NDrKohPQ+hxp0muBcBKrzKNtHr55DbqSx9hLsYVNnomSAMRAtI7R64t3gf3ID7tHQA7mG4oL3Hu9hdw==", + "dependencies": { + "debug": "^4.3.0", + "lru-cache": "^4.0.3" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/memorystore/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/memorystore/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/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minami": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/minami/-/minami-1.2.3.tgz", + "integrity": "sha512-3f2QqqbUC1usVux0FkQMFYB73yd9JIxmHSn1dWQacizL6hOUaNu6mA3KxZ9SfiCc4qgcgq+5XP59+hP7URa1Dw==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", + "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", + "dev": true + }, + "node_modules/mocha": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.0.tgz", + "integrity": "sha512-kNn7E8g2SzVcq0a77dkphPsDSN7P+iYkqE0ZsGCYWRsoiKjOt+NvXfaagik8vuDa6W5Zw3qxe8Jfpt5qKf+6/Q==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.2.0", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.34", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", + "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.5.tgz", + "integrity": "sha512-l29WGHAc0EayK1cjb6moozc+rlgK6YRCPbP3zB1CrJw84Bjk4kG9EJCXojdn4r29lA80SCqxRKq1QJ87+Xevng==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt-packet/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/mqtt-packet/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/mqtt/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/mqtt/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mqtt/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/mqtt/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mri": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", + "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/multer/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/multer/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/multer/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/nanoid": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nested-error-stacks": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", + "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==", + "dev": true + }, + "node_modules/nise": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", + "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^10.0.2", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", + "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0" + } + }, + "node_modules/nise/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==", + "dev": true + }, + "node_modules/nise/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-red": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/node-red/-/node-red-2.2.3.tgz", + "integrity": "sha512-sfOsWONOF5TyNApXv6AkLzwfxq+C+3lyUrXRvyuQxWt1dSGvfg417dbEx4WW0kxwREGZ47TKtLejnoTPnV5adQ==", + "dependencies": { + "@node-red/editor-api": "2.2.3", + "@node-red/nodes": "2.2.3", + "@node-red/runtime": "2.2.3", + "@node-red/util": "2.2.3", + "basic-auth": "2.0.1", + "bcryptjs": "2.4.3", + "express": "4.17.2", + "fs-extra": "10.0.0", + "node-red-admin": "^2.2.3", + "nopt": "5.0.0", + "semver": "7.3.5" + }, + "bin": { + "node-red": "red.js", + "node-red-pi": "bin/node-red-pi" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + } + }, + "node_modules/node-red-admin": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/node-red-admin/-/node-red-admin-2.2.4.tgz", + "integrity": "sha512-DlJpMFopqBNj10k5rGGI9ZNBi+whAIS+IHrSZH1xllfuJKZxQBZgR+o+rJeufDyc0OBRgHRqmX776HrBrlDtMA==", + "dependencies": { + "ansi-colors": "^4.1.1", + "axios": "0.27.0", + "bcryptjs": "^2.4.3", + "cli-table": "^0.3.11", + "enquirer": "^2.3.6", + "minimist": "^1.2.6", + "mustache": "^4.2.0", + "read": "^1.0.7" + }, + "bin": { + "node-red-admin": "node-red-admin.js" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + } + }, + "node_modules/node-red-contrib-pythonshell": { + "version": "1.5.4", + "resolved": "git+ssh://git@github.com/namgk/node-red-contrib-pythonshell.git#6bcc7df0003600bde8d688ece9c8d20caa00992f", + "license": "ISC" + }, + "node_modules/node-red-node-test-helper": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/node-red-node-test-helper/-/node-red-node-test-helper-0.2.7.tgz", + "integrity": "sha512-OanSQ1hrsigHVtMjL/cuhtjxhTdRBXxd3IALJC9eg0WOHRF75ZI7RYhFWqqOsvQ++BwmNj8ki1S49D8cZyZTWA==", + "dev": true, + "dependencies": { + "body-parser": "1.19.0", + "express": "4.17.1", + "read-pkg-up": "7.0.1", + "semver": "7.3.4", + "should": "^13.2.3", + "should-sinon": "0.0.6", + "sinon": "9.2.4", + "stoppable": "1.1.0", + "supertest": "4.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/node-red-node-test-helper/node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/node-red-node-test-helper/node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "dev": true, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/node-red-node-test-helper/node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/node-red-node-test-helper/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-red-node-test-helper/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/node-red-node-test-helper/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/node-red-node-test-helper/node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/nise/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==", + "dev": true + }, + "node_modules/node-red-node-test-helper/node_modules/nise/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/node-red-node-test-helper/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/node-red-node-test-helper/node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-red-node-test-helper/node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "node_modules/node-red-node-test-helper/node_modules/sinon": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/node-red-node-test-helper/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", + "dev": true, + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/superagent/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/node-red-node-test-helper/node_modules/supertest": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", + "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^3.8.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/nodemon": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", + "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5", + "update-notifier": "^5.1.0" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nodemon/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-allocator/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/number-allocator/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/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/nyc/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/nyc/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/nyc/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/nyc/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/nyc/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nyc/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/nyc/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/oauth2orize": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/oauth2orize/-/oauth2orize-1.11.1.tgz", + "integrity": "sha512-9dSx/Gwm0J2Rvj4RH9+h7iXVnRXZ6biwWRgb2dCeQhCosODS0nYdM9I/G7BUGsjbgn0pHjGcn1zcCRtzj2SlRA==", + "dependencies": { + "debug": "2.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-get": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", + "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", + "dev": true + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-to-spawn-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", + "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "dev": true, + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opted": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/opted/-/opted-1.0.2.tgz", + "integrity": "sha512-uEvunmdmKcSFiBSmnY2E9E/HbghO5yc1J0yNmq7T18YkAJeWNlo33e6VYKkRK4eudVrpvvlLdemAeAuL6rZxjQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/package-json/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/package-json/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/package-json/node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/got/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "node_modules/package-json/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/package-json/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/package-json/node_modules/responselike/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/pad-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pad-stream/-/pad-stream-2.0.0.tgz", + "integrity": "sha512-3QeQw19K48BQzUGZ9dEf/slX5Jbfy5ZeBTma2XICketO7kFNK7omF00riVcecOKN+DSiJZcK2em1eYKaVOeXKg==", + "dev": true, + "dependencies": { + "pumpify": "^1.3.3", + "split2": "^2.1.1", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pad-stream/node_modules/split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dev": true, + "dependencies": { + "through2": "^2.0.2" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.2.tgz", + "integrity": "sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-http-bearer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", + "integrity": "sha512-SELQM+dOTuMigr9yu8Wo4Fm3ciFfkMq5h/ZQ8ffi4ELgZrX1xh9PlglqZdcUZ1upzJD/whVyt+YWF62s3U6Ipw==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2-client-password": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/passport-oauth2-client-password/-/passport-oauth2-client-password-0.1.2.tgz", + "integrity": "sha512-GHQH4UtaEZvCLulAxGKHYoSsPRoPRmGsdmaZtMh5nmz80yMLQbdMA9Bg2sp4/UW3PIxJH/143hVjPTiXaNngTQ==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "dev": true, + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/proxy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/proxy/-/proxy-1.0.2.tgz", + "integrity": "sha512-KNac2ueWRpjbUh77OAFPZuNdfEqNynm9DD4xHT14CccGpW8wKZwEkN0yjlb7X9G9Z9F55N0Q+1z+WfgAhwYdzQ==", + "dev": true, + "dependencies": { + "args": "5.0.1", + "basic-auth-parser": "0.0.2", + "debug": "^4.1.1" + }, + "bin": { + "proxy": "bin/proxy.js" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/proxy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/pumpify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz", + "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", + "dev": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha512-QF8vjWx3wnRSL5uFMyCjDeDc5EBMiryoT9tz94VvgjKfzecHAVnqmXAwQDcr7X4JmLc2cjkjFGCVzhMqDjgR9g==", + "dev": true, + "dependencies": { + "test-value": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-extract/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-extract/node_modules/test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha512-wrsbRo7qP+2Je8x8DsK8ovCGyxe3sYfQwOraIY/09A2gFXU9DYKiTF14W4ki/01AEh56kMzAmlj9CaHGDDUBJA==", + "dev": true, + "dependencies": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-flatten": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", + "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reduce-unique": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", + "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha512-zQv5y/cf85sxvdrKPlfcRzlDn/OqKFThNimYmsS3flmkioKvkUGn2Qg9cJVoQiEvdxFGLE0MQER/9fZ9sUqdxg==", + "dev": true, + "dependencies": { + "test-value": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-without/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-without/node_modules/test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w==", + "dev": true, + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==" + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.6.1.tgz", + "integrity": "sha512-txv1qsctZq8ei9J/uCXgaKKFPjlBB0H2hvtnzw9rjKWFNUFtKh59WprXxpAeAey3/QeWwHdxMFqStPaOAgy+dA==", + "engines": { + "node": "*" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "devOptional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/safe-json-parse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "integrity": "sha512-o0JmTu17WGUaUOHa1l0FPGXKBfijbxK6qoHzlkihsDXxzBHvJcA7zgviKR92Xs841rX9pK16unfphLq0/KqX7A==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sass": { + "version": "1.49.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.7.tgz", + "integrity": "sha512-13dml55EMIR2rS4d/RDHHP0sXMY3+30e1TKsyXaSz3iLWVoDWEoboY8WzJd5JMnxrRHffKO3wq2mpJ0jxRJiEQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "devOptional": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", + "integrity": "sha512-C2FisSSW8S6TIYHHiMHN0NqzdjWfTekdMpA2FJTbRWnQMLO1RRIXEB9eVZYOlofYmjZA7fY3ChoFu09MeI3wlQ==", + "dev": true, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-sinon": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/should-sinon/-/should-sinon-0.0.6.tgz", + "integrity": "sha512-ScBOH5uW5QVFaONmUnIXANSR6z5B8IKzEmBP3HE5sPOCDuZ88oTMdUdnKoCVQdLcCIrRrhRLPS5YT+7H40a04g==", + "dev": true, + "peerDependencies": { + "should": ">= 8.x" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "devOptional": true + }, + "node_modules/simple-cli": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/simple-cli/-/simple-cli-5.0.5.tgz", + "integrity": "sha512-Er2FhsIayL/sktxg6fOCdNQJBTXhlf/fswNFsdmks88xsHzQ/IXGwxYgSSKeXBq4yqn83/iD4Sg8yjagwysUgw==", + "dev": true, + "dependencies": { + "async": "^3.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^7.0.0", + "key-list": "^0.1.4", + "lodash": "^4.17.15", + "opted": "^1.0.0" + } + }, + "node_modules/simple-cli/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-cli/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/simple-cli/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-cli/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/simple-cli/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/simple-cli/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/simple-cli/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-cli/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sinon": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", + "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sort-array": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.5.tgz", + "integrity": "sha512-Ya4peoS1fgFN42RN1REk2FgdNOeLIEMKFGJvs7VTP3OklF8+kl2SkpVliZ4tk/PurWsrWRsdNdU+tgyOBkB9sA==", + "dev": true, + "dependencies": { + "array-back": "^5.0.0", + "typical": "^6.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sort-array/node_modules/array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/sort-array/node_modules/typical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", + "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-wrap": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "dev": true, + "dependencies": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "node_modules/spawn-wrap/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/spawn-wrap/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/spawn-wrap/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true, + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/stream-buffers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", + "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha512-68Kl+79cE0RGKemKkhxTSg8+6AGrqBt+cbZAXevg2iJ6Y3zX4JhA/sZeGzLpxW9cXhmqAcE7KnJCisUmIUfnFQ==", + "dev": true, + "dependencies": { + "array-back": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-connect/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/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/string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==", + "dev": true + }, + "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==", + "devOptional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superagent": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", + "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.3", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.0.1", + "methods": "^1.1.2", + "mime": "^2.5.0", + "qs": "^6.10.3", + "readable-stream": "^3.6.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/superagent/node_modules/qs": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", + "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/superagent/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/superagent/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/supertest": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.2.2.tgz", + "integrity": "sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^7.1.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", + "dev": true + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha512-TvmyH7kC6ZVTYkqCODjJIbgvu0FKiwQpZ4D1aknE7xpcDf/qEOB8KZEK5ef2pfbVoiBhNWs3yx4y+ESMtNYmlg==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "dependencies": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/test-exclude/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/test-exclude/node_modules/read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/test-value/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tiny-lr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", + "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "dev": true, + "dependencies": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + } + }, + "node_modules/tiny-lr/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/tiny-lr/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/touch/node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/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/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "devOptional": true + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg==", + "dev": true + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz", + "integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "dev": true + }, + "node_modules/underscore.string": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", + "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", + "dev": true, + "dependencies": { + "sprintf-js": "^1.1.1", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/underscore.string/node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", + "integrity": "sha512-8pMuAn4KacYdGMkFaoQARicp4HSw24/DHOVKWqVRJ8LhhAwPPFpdGvdL9184JVmUwe7vz7Z9n6IqI6t5n2ELdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walk-back": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", + "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "devOptional": true + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "devOptional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "dependencies": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", + "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "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" + } + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/kubeflow/examples/package.json b/kubeflow/examples/package.json new file mode 100644 index 000000000..bd277eebc --- /dev/null +++ b/kubeflow/examples/package.json @@ -0,0 +1,127 @@ +{ + "name": "node-red", + "version": "2.2.3", + "description": "Low-code programming for event-driven applications", + "homepage": "http://nodered.org", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/node-red/node-red.git" + }, + "private": "true", + "scripts": { + "start": "node $NODE_OPTIONS node_modules/node-red/red.js", + "test": "grunt", + "build": "grunt build", + "dev": "grunt dev", + "build-dev": "grunt build-dev", + "docs": "grunt docs" + }, + "contributors": [ + { + "name": "Nick O'Leary" + }, + { + "name": "Dave Conway-Jones" + } + ], + "dependencies": { + "acorn": "8.7.0", + "acorn-walk": "8.2.0", + "ajv": "8.10.0", + "async-mutex": "0.3.2", + "basic-auth": "2.0.1", + "bcryptjs": "2.4.3", + "body-parser": "1.19.1", + "cheerio": "1.0.0-rc.10", + "clone": "2.1.2", + "content-type": "1.0.4", + "cookie": "0.4.2", + "cookie-parser": "1.4.6", + "cors": "2.8.5", + "cronosjs": "1.7.1", + "denque": "2.0.1", + "express": "4.17.2", + "express-session": "1.17.2", + "form-data": "4.0.0", + "fs-extra": "10.0.0", + "fs.notify": "0.0.4", + "got": "11.8.3", + "hash-sum": "2.0.0", + "hpagent": "0.1.2", + "https-proxy-agent": "5.0.0", + "i18next": "21.6.11", + "iconv-lite": "0.6.3", + "is-utf8": "0.2.1", + "js-yaml": "3.14.1", + "json-stringify-safe": "5.0.1", + "jsonata": "1.8.6", + "lodash.clonedeep": "^4.5.0", + "media-typer": "1.1.0", + "memorystore": "1.6.7", + "mime": "3.0.0", + "moment-timezone": "0.5.34", + "mqtt": "4.3.5", + "multer": "1.4.4", + "mustache": "4.2.0", + "node-red": "2.2.3", + "node-red-admin": "^2.2.3", + "node-red-contrib-pythonshell": "github:namgk/node-red-contrib-pythonshell", + "nopt": "5.0.0", + "oauth2orize": "1.11.1", + "on-headers": "1.0.2", + "passport": "0.5.2", + "passport-http-bearer": "1.0.1", + "passport-oauth2-client-password": "0.1.2", + "raw-body": "2.4.3", + "semver": "7.3.5", + "tar": "6.1.11", + "tough-cookie": "4.0.0", + "uglify-js": "3.15.1", + "uuid": "8.3.2", + "ws": "7.5.6", + "xml2js": "0.4.23" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + }, + "devDependencies": { + "dompurify": "2.3.6", + "grunt": "1.5.2", + "grunt-chmod": "~1.1.1", + "grunt-cli": "~1.4.3", + "grunt-concurrent": "3.0.0", + "grunt-contrib-clean": "~2.0.0", + "grunt-contrib-compress": "2.0.0", + "grunt-contrib-concat": "~1.0.1", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-jshint": "3.1.1", + "grunt-contrib-uglify": "5.0.1", + "grunt-contrib-watch": "~1.1.0", + "grunt-jsdoc": "2.4.1", + "grunt-jsdoc-to-markdown": "6.0.0", + "grunt-jsonlint": "2.1.3", + "grunt-mkdir": "~1.1.0", + "grunt-npm-command": "~0.1.2", + "grunt-sass": "~3.1.0", + "grunt-simple-mocha": "~0.4.1", + "grunt-simple-nyc": "^3.0.1", + "i18next-http-backend": "1.3.2", + "jquery-i18next": "1.2.1", + "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", + "marked": "4.0.12", + "minami": "1.2.3", + "mocha": "9.2.0", + "node-red-node-test-helper": "^0.2.7", + "nodemon": "2.0.15", + "proxy": "^1.0.2", + "sass": "1.49.7", + "should": "13.2.3", + "sinon": "11.1.2", + "stoppable": "^1.1.0", + "supertest": "6.2.2" + }, + "engines": { + "node": ">=12" + } +} diff --git a/kubeflow/examples/run.sh b/kubeflow/examples/run.sh new file mode 100644 index 000000000..daca187e0 --- /dev/null +++ b/kubeflow/examples/run.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +target=$1 + +if [ "$#" -eq 1 ] +then + USERDIR=/data/$target +else + USERDIR=/data/0.helloworld +fi + +echo "run with userdir=$USERDIR" + +USERDIR=$USERDIR docker compose up +#USERDIR=$USERDIR docker compose convert diff --git a/kubeflow/examples/scripts/entrypoint.sh b/kubeflow/examples/scripts/entrypoint.sh new file mode 100644 index 000000000..705054c0a --- /dev/null +++ b/kubeflow/examples/scripts/entrypoint.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +trap stop SIGINT SIGTERM + +function stop() { + kill $CHILD_PID + wait $CHILD_PID +} + +/usr/local/bin/node $NODE_OPTIONS node_modules/node-red/red.js --userDir $USERDIR & + +CHILD_PID="$!" + +wait "${CHILD_PID}" From 0870f9157ab5e6f9d592dd9ddc24fa6acee340cb Mon Sep 17 00:00:00 2001 From: NootNoot0 <161794667+NootNoot0@users.noreply.github.com> Date: Mon, 24 Jun 2024 16:17:51 +0800 Subject: [PATCH 2/3] Delete kubeflow directory --- kubeflow/LICENSE | 201 - kubeflow/README.md | 354 - kubeflow/examples/0.helloworld/flows.json | 101 - .../examples/0.helloworld/flows_cred.json | 3 - kubeflow/examples/0.helloworld/helloworld.py | 6 - kubeflow/examples/0.helloworld/package.json | 6 - kubeflow/examples/0.helloworld/settings.js | 498 - .../examples/1.connect-kubeflow/flows.json | 368 - .../1.connect-kubeflow/flows_cred.json | 3 - .../node_modules/nodepipe/LSTM.html | 149 - .../node_modules/nodepipe/LSTM.js | 66 - .../node_modules/nodepipe/LSTM0.js | 147 - .../node_modules/nodepipe/decisionTree0.js | 147 - .../node_modules/nodepipe/decisiontree.html | 149 - .../node_modules/nodepipe/decisiontree.js | 66 - .../node_modules/nodepipe/fl.html | 149 - .../node_modules/nodepipe/fl.js | 66 - .../node_modules/nodepipe/fl0.js | 147 - .../node_modules/nodepipe/mnist.html | 149 - .../node_modules/nodepipe/mnist.js | 66 - .../node_modules/nodepipe/mnist0.js | 147 - .../node_modules/nodepipe/package.json | 30 - .../examples/1.connect-kubeflow/package.json | 6 - .../examples/1.connect-kubeflow/py/LSTM.py | 132 - .../examples/1.connect-kubeflow/py/README.md | 18 - .../py/__pycache__/kfp_login.cpython-38.pyc | Bin 1992 -> 0 bytes .../py/__pycache__/kfp_login.cpython-39.pyc | Bin 2016 -> 0 bytes .../__pycache__/kfp_namespace.cpython-38.pyc | Bin 944 -> 0 bytes .../__pycache__/kfp_namespace.cpython-39.pyc | Bin 942 -> 0 bytes .../py/api_examples/create_experiment.py | 59 - .../py/api_examples/create_run.py | 58 - .../py/api_examples/delete_experiment.py | 51 - .../py/api_examples/delete_pipeline.py | 50 - .../py/api_examples/delete_run.py | 50 - .../py/api_examples/get_run.py | 64 - .../py/api_examples/kfp_login.py | 93 - .../py/api_examples/kfp_namespace.py | 19 - .../py/api_examples/list_experiments.py | 44 - .../py/api_examples/list_pipelines.py | 43 - .../py/api_examples/upload_pipeline.py | 52 - .../1.connect-kubeflow/py/decisionTree.py | 132 - kubeflow/examples/1.connect-kubeflow/py/fl.py | 132 - .../1.connect-kubeflow/py/helloworld.py | 6 - .../examples/1.connect-kubeflow/py/install.py | 23 - .../1.connect-kubeflow/py/kfp_example.py | 44 - .../1.connect-kubeflow/py/kfp_login.py | 93 - .../1.connect-kubeflow/py/kfp_namespace.py | 19 - .../examples/1.connect-kubeflow/py/mnist.py | 132 - .../py/pipelines/LSTM_pipeline.yaml | 651 - .../py/pipelines/fl_pipeline.yaml | 639 - .../py/pipelines/mnist_pipeline.yaml | 211 - .../py/pipelines/only_decision_tree.yaml | 131 - .../py/pipelines/three-pipeline.yaml | 229 - .../1.connect-kubeflow/py/requirements.txt | 2 - .../examples/1.connect-kubeflow/settings.js | 498 - kubeflow/examples/Dockerfile | 20 - kubeflow/examples/README.md | 40 - kubeflow/examples/build.sh | 3 - kubeflow/examples/docker-compose.yaml | 33 - kubeflow/examples/package-lock.json | 10782 ---------------- kubeflow/examples/package.json | 127 - kubeflow/examples/run.sh | 15 - kubeflow/examples/scripts/entrypoint.sh | 14 - 63 files changed, 17733 deletions(-) delete mode 100644 kubeflow/LICENSE delete mode 100644 kubeflow/README.md delete mode 100644 kubeflow/examples/0.helloworld/flows.json delete mode 100644 kubeflow/examples/0.helloworld/flows_cred.json delete mode 100644 kubeflow/examples/0.helloworld/helloworld.py delete mode 100644 kubeflow/examples/0.helloworld/package.json delete mode 100644 kubeflow/examples/0.helloworld/settings.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/flows.json delete mode 100644 kubeflow/examples/1.connect-kubeflow/flows_cred.json delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.html delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js delete mode 100644 kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json delete mode 100644 kubeflow/examples/1.connect-kubeflow/package.json delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/LSTM.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/README.md delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/decisionTree.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/fl.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/helloworld.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/install.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/kfp_example.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/kfp_login.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/mnist.py delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml delete mode 100644 kubeflow/examples/1.connect-kubeflow/py/requirements.txt delete mode 100644 kubeflow/examples/1.connect-kubeflow/settings.js delete mode 100644 kubeflow/examples/Dockerfile delete mode 100644 kubeflow/examples/README.md delete mode 100644 kubeflow/examples/build.sh delete mode 100644 kubeflow/examples/docker-compose.yaml delete mode 100644 kubeflow/examples/package-lock.json delete mode 100644 kubeflow/examples/package.json delete mode 100644 kubeflow/examples/run.sh delete mode 100644 kubeflow/examples/scripts/entrypoint.sh diff --git a/kubeflow/LICENSE b/kubeflow/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/kubeflow/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/kubeflow/README.md b/kubeflow/README.md deleted file mode 100644 index ecdb567e3..000000000 --- a/kubeflow/README.md +++ /dev/null @@ -1,354 +0,0 @@ -# Kube-node-red(en) -[![hackmd-github-sync-badge](https://hackmd.io/cocSOGQMR-qzo7DHdwgRsQ/badge)](https://hackmd.io/cocSOGQMR-qzo7DHdwgRsQ) - -Kube-node-red is aiming to integrate Kubeflow/Kubebeters with node-red, leveraging node-red's low-code modules, and using Kubeflow resources (e.g. Kubeflow pipeline, Kserve) to enhance its AI/ML ability. -## Table of Contents - - -- [Installation](#installation) - * [Prerequisites](#Prerequisites) - * [Building](#Building) - * [Install dependencies](#Install-dependencies) -- [Using our nodes](#Using-our-nodes) -- [Test python files to interact with kubeflow](#Test-python-files-to-interact-with-kubeflow) -- [possible problems and solution](#possible-problems-and-solution) -- [Modify your own custom nodes/pipeline](#Modify-your-own-custom-nodes/pipeline) - * [Kubeflow part](#Kubeflow-part) - * [Node-red part](#Node-red-part) -- [Architecture](#Architecture) -- [Demo](#Demo) -- [Reference](#Reference) - - - -# Installation -## Prerequisites -- `Kubeflow` -As this project focused on the node-red integration with Kubeflow, one running Kubeflow instance should be ready on a publicly available network. -(If you need to provision your own Kubeflow instance, you could refer to our [mulitkf](https://github.com/footprintai/multikf) project to allocate one instance for developing.) -- [`WSL`](https://learn.microsoft.com/en-us/windows/wsl/install) If you are Windows OS. -- [`Docker`](https://www.docker.com) - -## Building - -We organized some examples under examples folder, and make sensitive information pass via environment variables. Please refer the following example to launch an individual example: - -1. In terminal (If you on Windows system, please use WSL) -``` -$ git clone https://github.com/NightLightTw/kube-nodered.git -``` -2. Enter target folder -``` -cd kube-nodered/examples -``` -3. Enter account information and start -``` -KUBEFLOW_HOST= \ -KUBEFLOW_USERNAME= \ -KUBEFLOW_PASSWORD= \ -./run.sh -``` -> **Info:** Here please use 1.connect-kubeflow - -## Install dependencies - -1. Then you can go to UI, check it out: http://127.0.0.1:1880/ -![](https://hackmd.io/_uploads/HJ8Rbmdya.png) - -2. Click the “install dependency” button to install dependency items such as specific python libraries and wait for its completion -![](https://hackmd.io/_uploads/rygsMmuy6.png) - -3. Click the “list experiments” button to test the environment work! -![](https://hackmd.io/_uploads/HyXxfX_kp.png) - -## Using our nodes -Switch to the "three-pipeline" flow and press the button to trigger the pipeline process - -![](https://hackmd.io/_uploads/Hkr4mXdk6.png) - -On kubeflow: -![](https://hackmd.io/_uploads/H1_hEX_JT.png) - - - -> **Info:** If the environment variable does not work, please fill in the account password directly in the python file - - -## Test python files to interact with kubeflow -``` -# Open another terminal and check docker status -docker ps -#enter container -docker exec -it bash -#enter document folder -cd /data/1.connect-kubeflow/py/api_examples -#execute function -python3 -``` - -You can test the file in api_example -> **Info:** Some of these files require a custom name, description, or assigned id in - -## Possible problems and solution -Q1: MissingSchema Invalid URL '' - -A1: This problem means that the login information is not accessed correctly, which may be caused by the environment variable not being read. -You can directly override the login information of the specified file - -ex:![](https://hackmd.io/_uploads/ryx59rejBh.jpg) - -Change to your own login information -``` -host = "https://example@test.com" -username = "test01" -password = "123456" -``` - -# Modify your own custom nodes/pipeline -![implementation architecture](https://hackmd.io/_uploads/H1ZLgUsH2.png) - -## Kubeflow part -### Custom make pipeline’s yaml file -Please refer to [Kubeflow implementation:add Random Forest algorithm](https://hackmd.io/@Nhi7So-lTz2m5R6pHyCLcA/Sk1eZFTbh) - -### Take changing randomForest.py as an example - -Modify using your own yaml file path -> **Info:** Line 66: uploadfile='pipelines/only_randomforest.yaml' - -> **Info:** Line 122~129 use json parser for filtering different outputs from get_run() - -```python= -from __future__ import print_function - -import time -import kfp_server_api -import os -import requests -import string -import random -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -def random_suffix() -> string: - return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the Experiment API class - experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) - name="experiment-" + random_suffix() - description="This is a experiment for only_randomforest." - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey( - type=kfp_server_api.models.ApiResourceType.NAMESPACE, - id=resource_reference_key_id - ), - relationship=kfp_server_api.models.ApiRelationship.OWNER - )] - body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. - try: - # Creates a new experiment. - experiment_api_response = experiment_api_instance.create_experiment(body) - experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) - - # Create an instance of the pipeline API class - api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) - uploadfile='pipelines/only_randomforest.yaml' - name='pipeline-' + random_suffix() - description="This is a only_randomForest pipline." - try: - pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) - pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) - - # Create an instance of the run API class - run_api_instance = kfp_server_api.RunServiceApi(api_client) - display_name = 'run_only_randomForest' + random_suffix() - description = "This is a only_randomForest run." - pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), - relationship=kfp_server_api.models.ApiRelationship.OWNER )] - body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | - try: - # Creates a new run. - run_api_response = run_api_instance.create_run(body) - run_id = run_api_response.run.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling RunServiceApi->create_run: %s\n" % e) - - Completed_flag = False - polling_interval = 10 # Time in seconds between polls - - while not Completed_flag: - try: - time.sleep(1) - # Finds a specific run by ID. - api_instance = run_api_instance.get_run(run_id) - output = api_instance.pipeline_runtime.workflow_manifest - output = json.loads(output) - - try: - nodes = output['status']['nodes'] - conditions = output['status']['conditions'] # Comfirm completion. - - except KeyError: - nodes = {} - conditions = [] - - output_value = None - Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False - - except ApiException as e: - print("Exception when calling RunServiceApi->get_run: %s\n" % e) - break - - if not Completed_flag: - print("Pipeline is still running. Waiting...") - time.sleep(polling_interval-1) - - for node_id, node in nodes.items(): - if 'inputs' in node and 'parameters' in node['inputs']: - for parameter in node['inputs']['parameters']: - if parameter['name'] == 'random-forest-classifier-Accuracy': #change parameter - output_value = parameter['value'] - - if output_value is not None: - print(f"Random Forest Classifier Accuracy: {output_value}") - else: - print("Parameter not found.") - print(nodes) -``` - -## Node-red part -**Package nodered pyshell node** - -**A node mainly consists of two files** -* **Javascript file(.js)** -define what the node does -* **HTML file(.html)** -Define the properties of the node and the windows and help messages in the Node-RED editor - -**When finally package into npm module, will need package.json** - - -### **package.json** -A standard file for describing the content of node.js modules - -A standard package.json can be generated using npm init. This command will ask a series of questions to find a reasonable default value. When asked for the name of the module name: enter the example name node-red-contrib- - -When it is established, you need to manually add the node-red attribute -*p.s. Where the example files need to be changed * - - - -```json= -{ - "name": "node-red-contrib-pythonshell-custom", - ... - "node-red": { - "nodes": { - "decisionTree": "decisiontree.js", - "randomForest": "randomforest.js", - "logisticRegression": "logisticregression.js" - "":"" - } - }, - ... -} - -``` -### **HTML** -```javascript= - - - - - - - \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js deleted file mode 100644 index d16c5fe18..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2014 Sense Tecnic Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -var util = require("util"); -var httpclient; -var PythonshellNode = require('./LSTM0'); - -module.exports = function(RED) { - "use strict"; - - function PythonshellInNode(n) { - RED.nodes.createNode(this,n); - - var node = this; - node.config = n; // copy config to the backend so that down bellow we can have a reference - - var pyNode = new PythonshellNode(n); - - pyNode.setStatusCallback(node.status.bind(node)) - - node.on("input",function(msg) { - pyNode.onInput(msg, function(result){ - node.send(result); - }, function(err){ - node.error(err); - }); - }); - - node.on('close', ()=>pyNode.onClose()); - } - - RED.nodes.registerType("LSTM", PythonshellInNode); - - RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { - var node = RED.nodes.getNode(req.params.id); - if (node != null) { - try { - if (node.config.continuous){// see above comment - node.receive({payload: 'pythonshell@close'}) - } else { - node.receive(); - } - res.sendStatus(200); - } catch(err) { - res.sendStatus(500); - node.error(RED._("pythonshell.failed",{error:err.toString()})); - } - } else { - res.sendStatus(404); - } - }); - -} diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js deleted file mode 100644 index 86c0742f4..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js +++ /dev/null @@ -1,147 +0,0 @@ -var fs = require("fs"); - -function PythonshellInNode(config) { - if (!config.pyfile){ - throw 'pyfile not present'; - } - this.pythonExec = config.python3 ? "python3" : "python"; - this.pyfile = '/data/1.connect-kubeflow/py/LSTM.py'; - this.virtualenv = config.virtualenv; - - if (!fs.existsSync(this.pyfile)) { - throw 'pyfile not exist'; - } - - if (this.virtualenv && !fs.existsSync(this.virtualenv)){ - throw 'configured virtualenv not exist, consider remove or change'; - } - - this.stdInData = config.stdInData; - this.continuous = this.stdInData ? true : config.continuous; - this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); - this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); - this.spawn = require('child_process').spawn; - this.onStatus = ()=>{} -} - -PythonshellInNode.prototype.onInput = function(msg, out, err) { - payload = msg.payload || ''; - if (typeof payload === 'object'){ - payload = JSON.stringify(payload); - } else if (typeof payload !== 'string'){ - payload = payload.toString(); - } - - if (payload === 'pythonshell@close'){ - if (this.py != null){ - this.onClose() - return - } else { - // trigger new execution - payload = '' - } - } - - if (this.continuous && !this.stdInData && this.py != null){ - this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) - return - } - - var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec - - if (this.stdInData){ - if (!this.py){ - this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { - cwd: this.pydir, - detached: true - }); - this.firstExecution = true - } else { - this.firstExecution = false - } - } else { - this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { - cwd: this.pydir - }); - } - - this.onStatus({fill:"green",shape:"dot",text:"Standby"}) - - // subsequence message, no need to setup callbacks - if (this.stdInData && !this.firstExecution){ - this.py.stdin.write(payload + '\n') - return - } - - var py = this.py; - var dataString = ''; - var errString = ''; - - py.stdout.on('data', data => { - clearTimeout(this.standbyTimer) - - this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) - - let dataStr = data.toString(); - - dataString += dataStr; - - if (dataString.endsWith("\n")){ - if (this.continuous){ - msg.payload = dataString; - out(msg); - dataString = '' - } - } - - this.standbyTimer = setTimeout(()=>{ - this.onStatus({fill:"green",shape:"dot",text:"Standby"}) - }, 2000) - - }); - - py.stderr.on('data', data => { - errString += String(data);// just a different way to do it - this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) - }); - - py.stderr.on('error', console.log) - py.stdout.on('error', console.log) - py.stdin.on('error', console.log) - py.on('error', console.log) - - py.on('close', code =>{ - if (code){ - err('exit code: ' + code + ', ' + errString); - this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) - } else if (!this.continuous){ - msg.payload = dataString.trim(); - out(msg); - this.onStatus({fill:"green",shape:"dot",text:"Done"}) - } else { - this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) - } - this.py = null - setTimeout(()=>{ - this.onStatus({}) - }, 2000) - }); - - if (this.stdInData){ - py.stdin.write(payload + '\n') - } -}; - -PythonshellInNode.prototype.onClose = function() { - if (this.py){ - this.py.kill() - this.py = null - } -}; - -PythonshellInNode.prototype.setStatusCallback = function(callback) { - this.onStatus = callback -}; - - -module.exports = PythonshellInNode \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js deleted file mode 100644 index 7a8f3a690..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js +++ /dev/null @@ -1,147 +0,0 @@ -var fs = require("fs"); - -function PythonshellInNode(config) { - if (!config.pyfile){ - throw 'pyfile not present'; - } - this.pythonExec = config.python3 ? "python3" : "python"; - this.pyfile = "/data/1.connect-kubeflow/py/decisionTree.py"; - this.virtualenv = config.virtualenv; - - if (!fs.existsSync(this.pyfile)) { - throw 'pyfile not exist'; - } - - if (this.virtualenv && !fs.existsSync(this.virtualenv)){ - throw 'configured virtualenv not exist, consider remove or change'; - } - - this.stdInData = config.stdInData; - this.continuous = this.stdInData ? true : config.continuous; - this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); - this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); - this.spawn = require('child_process').spawn; - this.onStatus = ()=>{} -} - -PythonshellInNode.prototype.onInput = function(msg, out, err) { - payload = msg.payload || ''; - if (typeof payload === 'object'){ - payload = JSON.stringify(payload); - } else if (typeof payload !== 'string'){ - payload = payload.toString(); - } - - if (payload === 'pythonshell@close'){ - if (this.py != null){ - this.onClose() - return - } else { - // trigger new execution - payload = '' - } - } - - if (this.continuous && !this.stdInData && this.py != null){ - this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) - return - } - - var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec - - if (this.stdInData){ - if (!this.py){ - this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { - cwd: this.pydir, - detached: true - }); - this.firstExecution = true - } else { - this.firstExecution = false - } - } else { - this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { - cwd: this.pydir - }); - } - - this.onStatus({fill:"green",shape:"dot",text:"Standby"}) - - // subsequence message, no need to setup callbacks - if (this.stdInData && !this.firstExecution){ - this.py.stdin.write(payload + '\n') - return - } - - var py = this.py; - var dataString = ''; - var errString = ''; - - py.stdout.on('data', data => { - clearTimeout(this.standbyTimer) - - this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) - - let dataStr = data.toString(); - - dataString += dataStr; - - if (dataString.endsWith("\n")){ - if (this.continuous){ - msg.payload = dataString; - out(msg); - dataString = '' - } - } - - this.standbyTimer = setTimeout(()=>{ - this.onStatus({fill:"green",shape:"dot",text:"Standby"}) - }, 2000) - - }); - - py.stderr.on('data', data => { - errString += String(data);// just a different way to do it - this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) - }); - - py.stderr.on('error', console.log) - py.stdout.on('error', console.log) - py.stdin.on('error', console.log) - py.on('error', console.log) - - py.on('close', code =>{ - if (code){ - err('exit code: ' + code + ', ' + errString); - this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) - } else if (!this.continuous){ - msg.payload = dataString.trim(); - out(msg); - this.onStatus({fill:"green",shape:"dot",text:"Done"}) - } else { - this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) - } - this.py = null - setTimeout(()=>{ - this.onStatus({}) - }, 2000) - }); - - if (this.stdInData){ - py.stdin.write(payload + '\n') - } -}; - -PythonshellInNode.prototype.onClose = function() { - if (this.py){ - this.py.kill() - this.py = null - } -}; - -PythonshellInNode.prototype.setStatusCallback = function(callback) { - this.onStatus = callback -}; - - -module.exports = PythonshellInNode \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html deleted file mode 100644 index 2045d7745..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html +++ /dev/null @@ -1,149 +0,0 @@ -f - - - - - - - \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js deleted file mode 100644 index 1727299e0..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2014 Sense Tecnic Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -var util = require("util"); -var httpclient; -var PythonshellNode = require('./decisionTree0'); - -module.exports = function(RED) { - "use strict"; - - function PythonshellInNode(n) { - RED.nodes.createNode(this,n); - - var node = this; - node.config = n; // copy config to the backend so that down bellow we can have a reference - - var pyNode = new PythonshellNode(n); - - pyNode.setStatusCallback(node.status.bind(node)) - - node.on("input",function(msg) { - pyNode.onInput(msg, function(result){ - node.send(result); - }, function(err){ - node.error(err); - }); - }); - - node.on('close', ()=>pyNode.onClose()); - } - - RED.nodes.registerType("decisionTree", PythonshellInNode); - - RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { - var node = RED.nodes.getNode(req.params.id); - if (node != null) { - try { - if (node.config.continuous){// see above comment - node.receive({payload: 'pythonshell@close'}) - } else { - node.receive(); - } - res.sendStatus(200); - } catch(err) { - res.sendStatus(500); - node.error(RED._("pythonshell.failed",{error:err.toString()})); - } - } else { - res.sendStatus(404); - } - }); - -} diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html deleted file mode 100644 index 35f46a295..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html +++ /dev/null @@ -1,149 +0,0 @@ -f - - - - - - - \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js deleted file mode 100644 index edabfa19e..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2014 Sense Tecnic Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -var util = require("util"); -var httpclient; -var PythonshellNode = require('./fl0'); - -module.exports = function(RED) { - "use strict"; - - function PythonshellInNode(n) { - RED.nodes.createNode(this,n); - - var node = this; - node.config = n; // copy config to the backend so that down bellow we can have a reference - - var pyNode = new PythonshellNode(n); - - pyNode.setStatusCallback(node.status.bind(node)) - - node.on("input",function(msg) { - pyNode.onInput(msg, function(result){ - node.send(result); - }, function(err){ - node.error(err); - }); - }); - - node.on('close', ()=>pyNode.onClose()); - } - - RED.nodes.registerType("fl", PythonshellInNode); - - RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { - var node = RED.nodes.getNode(req.params.id); - if (node != null) { - try { - if (node.config.continuous){// see above comment - node.receive({payload: 'pythonshell@close'}) - } else { - node.receive(); - } - res.sendStatus(200); - } catch(err) { - res.sendStatus(500); - node.error(RED._("pythonshell.failed",{error:err.toString()})); - } - } else { - res.sendStatus(404); - } - }); - -} diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js deleted file mode 100644 index ee8b3f222..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js +++ /dev/null @@ -1,147 +0,0 @@ -var fs = require("fs"); - -function PythonshellInNode(config) { - if (!config.pyfile){ - throw 'pyfile not present'; - } - this.pythonExec = config.python3 ? "python3" : "python"; - this.pyfile = "/data/1.connect-kubeflow/py/fl.py"; - this.virtualenv = config.virtualenv; - - if (!fs.existsSync(this.pyfile)) { - throw 'pyfile not exist'; - } - - if (this.virtualenv && !fs.existsSync(this.virtualenv)){ - throw 'configured virtualenv not exist, consider remove or change'; - } - - this.stdInData = config.stdInData; - this.continuous = this.stdInData ? true : config.continuous; - this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); - this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); - this.spawn = require('child_process').spawn; - this.onStatus = ()=>{} -} - -PythonshellInNode.prototype.onInput = function(msg, out, err) { - payload = msg.payload || ''; - if (typeof payload === 'object'){ - payload = JSON.stringify(payload); - } else if (typeof payload !== 'string'){ - payload = payload.toString(); - } - - if (payload === 'pythonshell@close'){ - if (this.py != null){ - this.onClose() - return - } else { - // trigger new execution - payload = '' - } - } - - if (this.continuous && !this.stdInData && this.py != null){ - this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) - return - } - - var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec - - if (this.stdInData){ - if (!this.py){ - this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { - cwd: this.pydir, - detached: true - }); - this.firstExecution = true - } else { - this.firstExecution = false - } - } else { - this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { - cwd: this.pydir - }); - } - - this.onStatus({fill:"green",shape:"dot",text:"Standby"}) - - // subsequence message, no need to setup callbacks - if (this.stdInData && !this.firstExecution){ - this.py.stdin.write(payload + '\n') - return - } - - var py = this.py; - var dataString = ''; - var errString = ''; - - py.stdout.on('data', data => { - clearTimeout(this.standbyTimer) - - this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) - - let dataStr = data.toString(); - - dataString += dataStr; - - if (dataString.endsWith("\n")){ - if (this.continuous){ - msg.payload = dataString; - out(msg); - dataString = '' - } - } - - this.standbyTimer = setTimeout(()=>{ - this.onStatus({fill:"green",shape:"dot",text:"Standby"}) - }, 2000) - - }); - - py.stderr.on('data', data => { - errString += String(data);// just a different way to do it - this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) - }); - - py.stderr.on('error', console.log) - py.stdout.on('error', console.log) - py.stdin.on('error', console.log) - py.on('error', console.log) - - py.on('close', code =>{ - if (code){ - err('exit code: ' + code + ', ' + errString); - this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) - } else if (!this.continuous){ - msg.payload = dataString.trim(); - out(msg); - this.onStatus({fill:"green",shape:"dot",text:"Done"}) - } else { - this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) - } - this.py = null - setTimeout(()=>{ - this.onStatus({}) - }, 2000) - }); - - if (this.stdInData){ - py.stdin.write(payload + '\n') - } -}; - -PythonshellInNode.prototype.onClose = function() { - if (this.py){ - this.py.kill() - this.py = null - } -}; - -PythonshellInNode.prototype.setStatusCallback = function(callback) { - this.onStatus = callback -}; - - -module.exports = PythonshellInNode \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html deleted file mode 100644 index 322e0e99d..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html +++ /dev/null @@ -1,149 +0,0 @@ -f - - - - - - - \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js deleted file mode 100644 index 3c3e04c13..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2014 Sense Tecnic Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -var util = require("util"); -var httpclient; -var PythonshellNode = require('./mnist0'); - -module.exports = function(RED) { - "use strict"; - - function PythonshellInNode(n) { - RED.nodes.createNode(this,n); - - var node = this; - node.config = n; // copy config to the backend so that down bellow we can have a reference - - var pyNode = new PythonshellNode(n); - - pyNode.setStatusCallback(node.status.bind(node)) - - node.on("input",function(msg) { - pyNode.onInput(msg, function(result){ - node.send(result); - }, function(err){ - node.error(err); - }); - }); - - node.on('close', ()=>pyNode.onClose()); - } - - RED.nodes.registerType("mnist", PythonshellInNode); - - RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { - var node = RED.nodes.getNode(req.params.id); - if (node != null) { - try { - if (node.config.continuous){// see above comment - node.receive({payload: 'pythonshell@close'}) - } else { - node.receive(); - } - res.sendStatus(200); - } catch(err) { - res.sendStatus(500); - node.error(RED._("pythonshell.failed",{error:err.toString()})); - } - } else { - res.sendStatus(404); - } - }); - -} diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js deleted file mode 100644 index 58ebc34a3..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js +++ /dev/null @@ -1,147 +0,0 @@ -var fs = require("fs"); - -function PythonshellInNode(config) { - if (!config.pyfile){ - throw 'pyfile not present'; - } - this.pythonExec = config.python3 ? "python3" : "python"; - this.pyfile = "/data/1.connect-kubeflow/py/mnist.py"; - this.virtualenv = config.virtualenv; - - if (!fs.existsSync(this.pyfile)) { - throw 'pyfile not exist'; - } - - if (this.virtualenv && !fs.existsSync(this.virtualenv)){ - throw 'configured virtualenv not exist, consider remove or change'; - } - - this.stdInData = config.stdInData; - this.continuous = this.stdInData ? true : config.continuous; - this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); - this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); - this.spawn = require('child_process').spawn; - this.onStatus = ()=>{} -} - -PythonshellInNode.prototype.onInput = function(msg, out, err) { - payload = msg.payload || ''; - if (typeof payload === 'object'){ - payload = JSON.stringify(payload); - } else if (typeof payload !== 'string'){ - payload = payload.toString(); - } - - if (payload === 'pythonshell@close'){ - if (this.py != null){ - this.onClose() - return - } else { - // trigger new execution - payload = '' - } - } - - if (this.continuous && !this.stdInData && this.py != null){ - this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) - return - } - - var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec - - if (this.stdInData){ - if (!this.py){ - this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { - cwd: this.pydir, - detached: true - }); - this.firstExecution = true - } else { - this.firstExecution = false - } - } else { - this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { - cwd: this.pydir - }); - } - - this.onStatus({fill:"green",shape:"dot",text:"Standby"}) - - // subsequence message, no need to setup callbacks - if (this.stdInData && !this.firstExecution){ - this.py.stdin.write(payload + '\n') - return - } - - var py = this.py; - var dataString = ''; - var errString = ''; - - py.stdout.on('data', data => { - clearTimeout(this.standbyTimer) - - this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) - - let dataStr = data.toString(); - - dataString += dataStr; - - if (dataString.endsWith("\n")){ - if (this.continuous){ - msg.payload = dataString; - out(msg); - dataString = '' - } - } - - this.standbyTimer = setTimeout(()=>{ - this.onStatus({fill:"green",shape:"dot",text:"Standby"}) - }, 2000) - - }); - - py.stderr.on('data', data => { - errString += String(data);// just a different way to do it - this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) - }); - - py.stderr.on('error', console.log) - py.stdout.on('error', console.log) - py.stdin.on('error', console.log) - py.on('error', console.log) - - py.on('close', code =>{ - if (code){ - err('exit code: ' + code + ', ' + errString); - this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) - } else if (!this.continuous){ - msg.payload = dataString.trim(); - out(msg); - this.onStatus({fill:"green",shape:"dot",text:"Done"}) - } else { - this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) - } - this.py = null - setTimeout(()=>{ - this.onStatus({}) - }, 2000) - }); - - if (this.stdInData){ - py.stdin.write(payload + '\n') - } -}; - -PythonshellInNode.prototype.onClose = function() { - if (this.py){ - this.py.kill() - this.py = null - } -}; - -PythonshellInNode.prototype.setStatusCallback = function(callback) { - this.onStatus = callback -}; - - -module.exports = PythonshellInNode \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json b/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json deleted file mode 100644 index fcf46cd21..000000000 --- a/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "node-red-contrib-pythonshell-custom", - "version": "1.0.0", - "description": "modified version of node-red-contrib-pythonshell with additional features", - "scripts": { - "test": "./node_modules/mocha/bin/mocha" - }, - "keywords": [ - "distributed", - "python", - "node", - "node-red" - ], - "author": "WuChunYen", - "license": "ISC", - "dependencies": {}, - "node-red": { - "nodes": { - "decisionTree": "decisiontree.js", - "randomForest": "randomforest.js", - "logisticRegression": "logisticregression.js", - "fl": "fl.js", - "mnist": "mnist.js", - "LSTM": "LSTM.js" - } - }, - "devDependencies": { - "mocha": "^5.0.4" - } -} diff --git a/kubeflow/examples/1.connect-kubeflow/package.json b/kubeflow/examples/1.connect-kubeflow/package.json deleted file mode 100644 index b788fd491..000000000 --- a/kubeflow/examples/1.connect-kubeflow/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "node-red-project", - "description": "A Node-RED Project", - "version": "0.0.1", - "private": true -} \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/LSTM.py b/kubeflow/examples/1.connect-kubeflow/py/LSTM.py deleted file mode 100644 index 0eb2cb76a..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/LSTM.py +++ /dev/null @@ -1,132 +0,0 @@ -from __future__ import print_function - -import time -import kfp_server_api -import os -import requests -import string -import random -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = "https://ai4edu.thu01.footprint-ai.com" -username = "thu02" -password = "M*$3sNF7" - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -def random_suffix() -> string: - return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the Experiment API class - experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) - name="experiment-" + random_suffix() - description="This is a experiment for LSTM." - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey( - type=kfp_server_api.models.ApiResourceType.NAMESPACE, - id=resource_reference_key_id - ), - relationship=kfp_server_api.models.ApiRelationship.OWNER - )] - body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. - try: - # Creates a new experiment. - experiment_api_response = experiment_api_instance.create_experiment(body) - experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) - - # Create an instance of the pipeline API class - api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) - uploadfile='pipelines/LSTM_pipeline.yaml' - name='pipeline-' + random_suffix() - description="This is a LSTM pipline." - try: - pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) - pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) - - # Create an instance of the run API class - run_api_instance = kfp_server_api.RunServiceApi(api_client) - display_name = 'LSTM' + random_suffix() - description = "This is a LSTM run." - pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), - relationship=kfp_server_api.models.ApiRelationship.OWNER )] - body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | - try: - # Creates a new run. - run_api_response = run_api_instance.create_run(body) - run_id = run_api_response.run.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling RunServiceApi->create_run: %s\n" % e) - - Completed_flag = False - polling_interval = 10 # Time in seconds between polls - - while not Completed_flag: - try: - time.sleep(1) - # Finds a specific run by ID. - api_instance = run_api_instance.get_run(run_id) - output = api_instance.pipeline_runtime.workflow_manifest - output = json.loads(output) - - try: - nodes = output['status']['nodes'] - conditions = output['status']['conditions'] # Comfirm completion. - - except KeyError: - nodes = {} - conditions = [] - - output_value = None - Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False - - except ApiException as e: - print("Exception when calling RunServiceApi->get_run: %s\n" % e) - break - - if not Completed_flag: - print("Pipeline is still running. Waiting...") - time.sleep(polling_interval-1) - - for node_id, node in nodes.items(): - if 'inputs' in node and 'parameters' in node['inputs']: - for parameter in node['inputs']['parameters']: - if parameter['name'] == 'random-forest-classifier-Accuracy': #change parameter - output_value = parameter['value'] - - if output_value is not None: - print(f"Random Forest Classifier Accuracy: {output_value}") - else: - print("Parameter not found.") - print(nodes) diff --git a/kubeflow/examples/1.connect-kubeflow/py/README.md b/kubeflow/examples/1.connect-kubeflow/py/README.md deleted file mode 100644 index 06bb167e4..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/README.md +++ /dev/null @@ -1,18 +0,0 @@ -## How to use -``` -KUBEFLOW_HOST= \ -KUBEFLOW_USERNAME= \ -KUBEFLOW_PASSWORD= \ -python3 -``` -## three pipelines -流程架構: -create_experiment -> upload_pipeline -> create_run -> get_run -> filter -> result -### decisionTree.py -功能:以乳癌資料集訓練decisionTree模型並回傳準確率 - -### logisticRegression.py -功能:以乳癌資料集訓練logisticRegression模型並回傳準確率 - -### randomForest.py -功能:以乳癌資料集訓練randomForest模型並回傳準確率 diff --git a/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc b/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc deleted file mode 100644 index 193a91af9ab988978f2373b5b3ad1d940277f916..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1992 zcmah}&2JM&6rb5IZ=AIg0;F(h=YRx`iqlH%#dQ(1Q2G(2Aqh$qR5|ONak9>OXPKEL z#Bwf$V^QguR7%uS@BJfs?0K*4g@1txrEg|!6rfUPwe#`jz2Cg=yR}*s!MJn%9{aJ5 z&|ms+dbn`74!`^eCWQUXVas24K=*yAc>Y6 zxbSn4$SjFf!zpao13@y8h67gkSt#Wm7qsvMQ@KbZTT6{c1y-%*=kUu17@-j;GXAVX z_rO-@2p^-T_@~taXXNxPxVNeE#5!+9^oG_P~4GC z{Weniw(x`-a(15ZsIRcSEt`qRgj z_#M^&C^Z_;nxWaW{$#>6Gv@kp(I0iDjaQTmzD*-+lp`zaRwYnmIbH?#)~K$y{J z7tsihEPCe90;IVo_JMoaESfq@3N+Qm8W7agl8#h*$zgoWCB0Nn>$t|fu6-O)M43S#~YisG|jTPAD z@OTQ>zye62U<95OKmuu*XBiiYQG=}2Hsi`3Bb4>RJW;P!P%D>lx=r4G4GipZwPUbZ z8g>&!kY%0dwi2&8h0e3N%sFX4M&lz6~|_QLxlPNO8J8a5ML@rWm{$&ItWWgPVO z!(5QDm6JL-Ej_82|CgR{meOT?wT$OpMIcUlTnvm44cBtR-3(YtGajd^qiZ#QSjK`y z<*7#5!%o7tS*Uh~GbORP z0CZ6AlJG&KVHK`93f<4(YwM8GEi$w|A(7T`GA!8W$JXGN@4~bVUF-Y#13bcg=spzcw2z?z z?Vqjt4%8NYfj`xXnRe*Hi#da%)%>8q(Qinc2ZR?_7PZ=oA2uVNrVxs&yW^x=%=Q;| zds!KgX0~5c+es`{#0S~6ds+bpCJ!3faABLN4qU~&qn!v*GbPw;8!yUhu$c%7-Etdq zg)i9soJl2%%38@?*nm<@m!X3=Q&t44IXG{?ZVADK(9OHB6P6a09f0FvUub_6mSBY^ zStz0%QPTt;k|ImOh!wWXyM+h1I@z3zOI0|1$iAXd=8X$uN03r8@S zZO%?&q*JrQyM5!la+=qV&i}U$behRkm{85acLTd_ zIktGLfte2iU3$)f55|Eg2qzwBht#$B)QQdD3IL#AwO{bdlVDfQb`S!olK{pft diff --git a/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc b/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc deleted file mode 100644 index 37989316f586bdf924c9c0c085096deb6c4817a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2016 zcmah~&u<(x6t-tPvzyKCCQaKwFUW^V?H0OeB~HsywUAJLR3S8hid3+j9eb16%#NqF zr)i>zgh-DR%DF{Kj{F1s4V*d76)rvZR)oT{XSYgQBs>~>{QTbM=l8wm2^x(Wg7(GL z+x&+nLVudc@#ewgD!l4l=on%+M(bvDVmxxz9bC%Xb(a(Sc+7o57-8N6vhFjyidz0t zutdu(TvRg|t2B;uixe(=gFtba1S4Kl(?F?hAz9%|t}~g0uCW@o3XD~FKZIBPh!M)c zk@4d^@%CJe4)7s*gn#;WkK|bDF=CY*Jx0Hfef&KJ ziI=;q+C|!|R`xNQ+Hz#hY9O8NqTIcO9N3K@g7#gERsp$O(N$x22JPcLUr!y>SUvZL z(}#}y4aPc18m!J5R_3zi!->|+SnH46KWH8TKAY{Lc-sQsx^{EeZ za4S<$vO!7{ss(NdvvPJ5vhV7eEf~ot5T7X*q>wr_$VWFe5C`ft)sIOE-)j4Z%B;NI|UV zHit9<#`-|^4v=^+h$BWX(q%y>XQ06V3V^PBzPbh}-J!eAdo(mYPMQNBX0ugz)mzYQ zz-{);{2tEn5N;&~)jPycm+sHbT>`a*pX2w9WA>W#V8@KZ)M;NTaQG{drvc&l`32+l z!sT`-k_4!@xHV3?g>+|OYmkSi2HsF}?qJA@jz>WBlltM~#p%-q< zlcKT-a6;}#6N|!;yzmtdWVk6CMo@)>NaG;ng{!iD;RCKoG?EIX3o?YvD=K9UsaD0p zN&Tc5^xOwEmYSWv;bQT!uvMEs5;-v(qj z1cjlfgKKfrZ^PvQ7l4V4JY(dp(h?Fg3bj=~=D8tXTKB8nkziTOub5O*K6F)FcdG8c DjCnfW diff --git a/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc b/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc deleted file mode 100644 index d49512c6312c4543713547c31315654ef7d280c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 944 zcmZuuO-~y!5cSuFBqRudgvh1Z8;Vqtw#O<(NCmYg)Ry#;s*1L2Cv38@7uyR;w2`X9 zwTGT*RXFya^f&n06MumVolQ#M(2?fZV|&Ik@4c^9%Lwf4?g#OcAoM2>9vXvS7u-Ap z;E3ZGb>=JXV2DXfMzljQ5=>CRIQ>pJ(3EDFlN!3DoL=E6 zvn*qr)zBHn2zFi#WpsYhLe?7;GLlhV_)4Z;<_(tk(va$bE%IU>T_9e{$OZbr&hQt^ z%Y6A9W!`1!3h_z}?Lkc#sCqEj2$HCIs`Rk0Rhl$~JlT$9Pq~$UlXOF+hLO0zFEoah zuX6wbmgdLi`ZvUrwb$+T8{gQ#rp6By7yi~{ear7D?Z4V@`$0d5q_NNaFwefToSIyb zLvZ5*^ihUBZcZ_ffNDU>kZ3k1a>}Ro5NnxT@+{}V^?m)k+Go~B|B?*OSxPH zL~!MHvIT1DNSuiK4AW@EDhy(?1Dm@%S6);!^|B+%IF!6t}vRUsUJ1 zbgdc+3BPL~=$;Y13UA!{f2PTYH5&j3uMmb;a0RadmNCJrw~XpXa04Bz!=g6uf&19JUS8RN5`{sO@%_O$>2 diff --git a/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc b/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc deleted file mode 100644 index 6c29c28cec6281c9c0c84d4df70e3ff04056ed1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 942 zcmZuvO-~y!5cSuFBqRudgvh1Z8;VqtmSdG7q=MQLYD-S3s%X1*!X_JgvAv)~8>uQ> zd+3=~g=7Coe}k_*@fWzz*`x#x9m&t0wP)tdn+>YfG6H+I_d)z52>r>O$Hu_fgJpIA zIN~@)o%xPC7<>|w5$#Zn1QS#+PQO#mxOc%i9>+(hUbulcbXdo()E*~-??<7nQ^$^# zv91!N_PA?=F_Dt4poLAf41vbN3UKmZy@F*v16VY`S0n=>*JMf}G^H8lq=v32r`LGO zEXx>YHFS zBUr`<=%WmM+?-+%0o6d1A<=9u$TxDrfG+JYtzzLkbtZ*&B^iu_NrF)PLUrOua3ZJo5NnxT_k8EV^?m)k+Go~CA(`mrJP$4 zSMDZTFiRbYQ}OWLG+MC=gV^lC;XcZh7x_%R?1(asC4oJ5Y@j0PJd?zcbzY()XKf#E&_l1n8@K+SZt_3VYycpq#ssh4F{+=y4KP@TO>Y9Yf*mK3 k?CX4njvA|HPac(;4PjQV*cvIG#$q?0y~!&TagkKWU&grhzW@LL diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py deleted file mode 100644 index 8ac8d7321..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py +++ /dev/null @@ -1,59 +0,0 @@ -from __future__ import print_function -import string -import random -import time -import kfp_server_api -import os -import requests -import kfp -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.ExperimentServiceApi(api_client) - name="" # str | The ID of the name to be create. - description='' # str | The description experiment. - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey( - type=kfp_server_api.models.ApiResourceType.NAMESPACE, - id=resource_reference_key_id - ), - relationship=kfp_server_api.models.ApiRelationship.OWNER - )] - body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. - try: - # Creates a new experiment. - api_response = api_instance.create_experiment(body) - pprint(api_response) - except ApiException as e: - print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py deleted file mode 100644 index b02691de7..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import print_function -import string -import random -import time -import kfp_server_api -import os -import requests -import kfp -import json -from pprint import pprint -from kfp_server_api.rest import ApiException -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.RunServiceApi(api_client) - pipeline_id = '' # str | The ID of the pipeline. - experiment_id = '' # str | The ID of the experiment. - display_name = '' # str | The name of the run to be create. - description = '' # str | The description of run. - pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), - relationship=kfp_server_api.models.ApiRelationship.OWNER )] - body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | - - try: - # Creates a new run. - api_response = api_instance.create_run(body) - pprint(api_response) - except ApiException as e: - print("Exception when calling RunServiceApi->create_run: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py deleted file mode 100644 index 31d9205c7..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py +++ /dev/null @@ -1,51 +0,0 @@ -from __future__ import print_function -import string -import random -import time -import kfp_server_api -import os -import requests -import kfp -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.ExperimentServiceApi(api_client) - experiment_id = '' # str | The ID of the experiment to be deleted. - - try: - # Deletes an experiment without deleting the experiment's runs and recurring runs. - # To avoid unexpected behaviors, delete an experiment's runs and recurring runs before deleting the experiment. - api_response = api_instance.delete_experiment(experiment_id) - pprint(api_response) - except ApiException as e: - print("Exception when calling ExperimentServiceApi->delete_experiment: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py deleted file mode 100644 index c04d595ef..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import print_function -import string -import random -import time -import kfp_server_api -import os -import requests -import kfp -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.PipelineServiceApi(api_client) - id = '' # str | The ID of the pipeline to be deleted. - - try: - # Deletes a pipeline and its pipeline versions. - api_response = api_instance.delete_pipeline(id) - pprint(api_response) - except ApiException as e: - print("Exception when calling PipelineServiceApi->delete_pipeline: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py deleted file mode 100644 index aefc7dca3..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import print_function -import string -import random -import time -import kfp_server_api -import os -import requests -import kfp -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.RunServiceApi(api_client) - id = '' # str | The ID of the run to be deleted. - - try: - # Deletes a run. - api_response = api_instance.delete_run(id) - pprint(api_response) - except ApiException as e: - print("Exception when calling RunServiceApi->delete_run: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py deleted file mode 100644 index f62c56bdc..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py +++ /dev/null @@ -1,64 +0,0 @@ -from __future__ import print_function - -import time -import kfp_server_api -import os -import requests -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces -import json - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.RunServiceApi(api_client) - run_id = '' # str | The ID of the run to be retrieved. - - try: - # Finds a specific run by ID. - api_response = api_instance.get_run(run_id) - output = api_response.pipeline_runtime.workflow_manifest - output = json.loads(output) - nodes = output['status']['nodes'] - conditions = output['status']['conditions'] # Comfirm completion. - output_value = None - - for node_id, node in nodes.items(): - if 'inputs' in node and 'parameters' in node['inputs']: - for parameter in node['inputs']['parameters']: - if parameter['name'] == 'decision-tree-classifier-Accuracy': - output_value = parameter['value'] - break - - if output_value is not None: - print(f"Decision Tree Classifier Accuracy: {output_value}") - else: - print("Parameter not found.") - except ApiException as e: - print("Exception when calling RunServiceApi->get_run: %s\n" % e) diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py deleted file mode 100644 index 7c95abcf0..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py +++ /dev/null @@ -1,93 +0,0 @@ -import re -from urllib.parse import urlsplit - -import requests - -# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916 -def get_istio_auth_session(url: str, username: str, password: str) -> dict: - """ - Determine if the specified URL is secured by Dex and try to obtain a session cookie. - WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported - (we default default to using `staticPasswords` if both are enabled) - - :param url: Kubeflow server URL, including protocol - :param username: Dex `staticPasswords` or `LDAP` username - :param password: Dex `staticPasswords` or `LDAP` password - :return: auth session information - """ - # define the default return object - auth_session = { - "endpoint_url": url, # KF endpoint URL - "redirect_url": None, # KF redirect URL, if applicable - "dex_login_url": None, # Dex login URL (for POST of credentials) - "is_secured": None, # True if KF endpoint is secured - "session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2" - } - - # use a persistent session (for cookies) - with requests.Session() as s: - - ################ - # Determine if Endpoint is Secured - ################ - resp = s.get(url, allow_redirects=True) - if resp.status_code != 200: - raise RuntimeError( - f"HTTP status code '{resp.status_code}' for GET against: {url}" - ) - - auth_session["redirect_url"] = resp.url - - # if we were NOT redirected, then the endpoint is UNSECURED - if len(resp.history) == 0: - auth_session["is_secured"] = False - return auth_session - else: - auth_session["is_secured"] = True - - ################ - # Get Dex Login URL - ################ - redirect_url_obj = urlsplit(auth_session["redirect_url"]) - - # if we are at `/auth?=xxxx` path, we need to select an auth type - if re.search(r"/auth$", redirect_url_obj.path): - # default to "staticPasswords" auth type - redirect_url_obj = redirect_url_obj._replace( - path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path) - ) - - # if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST) - if re.search(r"/auth/.*/login$", redirect_url_obj.path): - auth_session["dex_login_url"] = redirect_url_obj.geturl() - - # else, we need to be redirected to the actual login page - else: - # this GET should redirect us to the `/auth/xxxx/login` path - resp = s.get(redirect_url_obj.geturl(), allow_redirects=True) - if resp.status_code != 200: - raise RuntimeError( - f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}" - ) - - # set the login url - auth_session["dex_login_url"] = resp.url - - ################ - # Attempt Dex Login - ################ - resp = s.post( - auth_session["dex_login_url"], - data={"login": username, "password": password}, - allow_redirects=True - ) - if len(resp.history) == 0: - raise RuntimeError( - f"Login credentials were probably invalid - " - f"No redirect after POST to: {auth_session['dex_login_url']}" - ) - - # store the session cookies in a "key1=value1; key2=value2" string - auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies]) - - return auth_session \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py deleted file mode 100644 index 3c7c0dfdc..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py +++ /dev/null @@ -1,19 +0,0 @@ -import os -import requests - -from typing import TypedDict - -def retrieve_namespaces(host: str, auth_session: TypedDict) -> str: - workgroup_endpoint = os.path.join(host, "api/workgroup/env-info") - - cookies = {} - cookie_tokens = auth_session["session_cookie"].split("=") - print(cookie_tokens[0]) - cookies[cookie_tokens[0]]=cookie_tokens[1] - resp = requests.get(workgroup_endpoint, cookies=cookies) - if resp.status_code != 200: - raise RuntimeError( - f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}" - ) - return [ns["namespace"] for ns in resp.json()["namespaces"] if - ns["role"]=="owner"] \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py deleted file mode 100644 index 2e4729bea..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import print_function - -import time -import kfp_server_api -import os -import requests -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -print("available namespace: {}".format(namespaces)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.ExperimentServiceApi(api_client) - resource_reference_key_type = "NAMESPACE" - resource_reference_key_id = namespaces[0] - list_experiment_response = api_instance.list_experiment(resource_reference_key_type=resource_reference_key_type, resource_reference_key_id=resource_reference_key_id) - for experiment in list_experiment_response.experiments: - pprint(experiment) diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py deleted file mode 100644 index 6e2be4b5e..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py +++ /dev/null @@ -1,43 +0,0 @@ -from __future__ import print_function -import string -import time -import kfp_server_api -import os -import requests -import kfp -import json -from pprint import pprint -from kfp_server_api.rest import ApiException -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - api_instance = kfp_server_api.PipelineServiceApi(api_client) - list_pipeline_response = api_instance.list_pipelines() - for pipelines in list_pipeline_response.pipelines: - print(pipelines) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py b/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py deleted file mode 100644 index 410cf50aa..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py +++ /dev/null @@ -1,52 +0,0 @@ -from __future__ import print_function -import string -import random -import time -import kfp_server_api -import os -import requests -from kfp_server_api.rest import ApiException - -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - - -host = os.getenv("KUBEFLOW_HOST") -username = os.getenv("KUBEFLOW_USERNAME") -password = os.getenv("KUBEFLOW_PASSWORD") - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -print("available namespace: {}".format(namespaces)) - -def random_suffix() -> string: - return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) - uploadfile='' # The yaml file in your local path. - name='pipeline-' + random_suffix() - description='' # str | The description of pipeline. - try: - api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) - print(api_response) - except ApiException as e: - print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py b/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py deleted file mode 100644 index 16293f1d6..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py +++ /dev/null @@ -1,132 +0,0 @@ -from __future__ import print_function - -import time -import kfp_server_api -import os -import requests -import string -import random -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = "http://ai4edu.thu01.footprint-ai.com" -username = "thu02" -password = "M*$3sNF7" - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -def random_suffix() -> string: - return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the Experiment API class - experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) - name="experiment-" + random_suffix() - description="This is a experiment for only_decision_tree." - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey( - type=kfp_server_api.models.ApiResourceType.NAMESPACE, - id=resource_reference_key_id - ), - relationship=kfp_server_api.models.ApiRelationship.OWNER - )] - body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. - try: - # Creates a new experiment. - experiment_api_response = experiment_api_instance.create_experiment(body) - experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) - - # Create an instance of the pipeline API class - api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) - uploadfile='pipelines/only_decision_tree.yaml' - name='pipeline-' + random_suffix() - description="This is a only_decision_tree pipline." - try: - pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) - pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) - - # Create an instance of the run API class - run_api_instance = kfp_server_api.RunServiceApi(api_client) - display_name = 'run_only_decision_tree' + random_suffix() - description = "This is a only_decision_tree run." - pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), - relationship=kfp_server_api.models.ApiRelationship.OWNER )] - body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | - try: - # Creates a new run. - run_api_response = run_api_instance.create_run(body) - run_id = run_api_response.run.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling RunServiceApi->create_run: %s\n" % e) - - Completed_flag = False - polling_interval = 10 # Time in seconds between polls - - while not Completed_flag: - try: - time.sleep(1) - # Finds a specific run by ID. - api_instance = run_api_instance.get_run(run_id) - output = api_instance.pipeline_runtime.workflow_manifest - output = json.loads(output) - - try: - nodes = output['status']['nodes'] - conditions = output['status']['conditions'] # Comfirm completion. - - except KeyError: - nodes = {} - conditions = [] - - output_value = None - Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False - - except ApiException as e: - print("Exception when calling RunServiceApi->get_run: %s\n" % e) - break - - if not Completed_flag: - print("Pipeline is still running. Waiting...") - time.sleep(polling_interval-1) - - for node_id, node in nodes.items(): - if 'inputs' in node and 'parameters' in node['inputs']: - for parameter in node['inputs']['parameters']: - if parameter['name'] == 'decision-tree-classifier-Accuracy': - output_value = parameter['value'] - - if output_value is not None: - print(f"Decision Tree Classifier Accuracy: {output_value}") - else: - print("Parameter not found.") - print(nodes) diff --git a/kubeflow/examples/1.connect-kubeflow/py/fl.py b/kubeflow/examples/1.connect-kubeflow/py/fl.py deleted file mode 100644 index 6aeb83f9d..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/fl.py +++ /dev/null @@ -1,132 +0,0 @@ -from __future__ import print_function - -import time -import kfp_server_api -import os -import requests -import string -import random -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = "https://ai4edu.thu01.footprint-ai.com" -username = "thu02" -password = "M*$3sNF7" - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -def random_suffix() -> string: - return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the Experiment API class - experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) - name="experiment-" + random_suffix() - description="This is a experiment for fl." - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey( - type=kfp_server_api.models.ApiResourceType.NAMESPACE, - id=resource_reference_key_id - ), - relationship=kfp_server_api.models.ApiRelationship.OWNER - )] - body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. - try: - # Creates a new experiment. - experiment_api_response = experiment_api_instance.create_experiment(body) - experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) - - # Create an instance of the pipeline API class - api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) - uploadfile='pipelines/fl_pipeline.yaml' - name='pipeline-' + random_suffix() - description="This is a fl pipline." - try: - pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) - pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) - - # Create an instance of the run API class - run_api_instance = kfp_server_api.RunServiceApi(api_client) - display_name = 'fl' + random_suffix() - description = "This is a fl run." - pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), - relationship=kfp_server_api.models.ApiRelationship.OWNER )] - body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | - try: - # Creates a new run. - run_api_response = run_api_instance.create_run(body) - run_id = run_api_response.run.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling RunServiceApi->create_run: %s\n" % e) - - Completed_flag = False - polling_interval = 10 # Time in seconds between polls - - while not Completed_flag: - try: - time.sleep(1) - # Finds a specific run by ID. - api_instance = run_api_instance.get_run(run_id) - output = api_instance.pipeline_runtime.workflow_manifest - output = json.loads(output) - - try: - nodes = output['status']['nodes'] - conditions = output['status']['conditions'] # Comfirm completion. - - except KeyError: - nodes = {} - conditions = [] - - output_value = None - Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False - - except ApiException as e: - print("Exception when calling RunServiceApi->get_run: %s\n" % e) - break - - if not Completed_flag: - print("Pipeline is still running. Waiting...") - time.sleep(polling_interval-1) - - for node_id, node in nodes.items(): - if 'inputs' in node and 'parameters' in node['inputs']: - for parameter in node['inputs']['parameters']: - if parameter['name'] == 'client-last_accuracy': - output_value = parameter['value'] - - if output_value is not None: - print(f"fl Accuracy: {output_value}") - else: - print("Parameter not found.") - print(nodes) diff --git a/kubeflow/examples/1.connect-kubeflow/py/helloworld.py b/kubeflow/examples/1.connect-kubeflow/py/helloworld.py deleted file mode 100644 index 97e823fb5..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/helloworld.py +++ /dev/null @@ -1,6 +0,0 @@ -import sys - -while True: - line = sys.stdin.readline() - print('this is send from python') - print(line) diff --git a/kubeflow/examples/1.connect-kubeflow/py/install.py b/kubeflow/examples/1.connect-kubeflow/py/install.py deleted file mode 100644 index 470d38321..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/install.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -import subprocess - -def python3_version(): - return subprocess.check_call(["python3", "--version"]) - -def which(command): - return subprocess.check_call(["which", command]) - -def pip3_install_requirements(): - return subprocess.check_call(["pip3", "install", "-r", "requirements.txt", - "--user"]) - -def pip3_install_kfp(): - return subprocess.check_call(["pip3", "install", - "git+https://github.com/kubeflow/pipelines.git@1.8.19#subdirectory=backend/api/python_http_client", - "--user"]) - -python3_version() -pip3_install_requirements() -pip3_install_kfp() - -print("done") diff --git a/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py b/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py deleted file mode 100644 index da7ef822f..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import print_function - -import time -import kfp_server_api -import os -import requests -from kfp_server_api.rest import ApiException - -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = "http://ai4edu.thu01.footprint-ai.com" -username = "thu02" -password = "M*$3sNF7" - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -print("available namespace: {}".format(namespaces)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the API class - api_instance = kfp_server_api.ExperimentServiceApi(api_client) - resource_reference_key_type = "NAMESPACE" - resource_reference_key_id = namespaces[0] - list_experiment_response = api_instance.list_experiment(resource_reference_key_type=resource_reference_key_type, resource_reference_key_id=resource_reference_key_id) - for experiment in list_experiment_response.experiments: - print(experiment) diff --git a/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py b/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py deleted file mode 100644 index 7c95abcf0..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py +++ /dev/null @@ -1,93 +0,0 @@ -import re -from urllib.parse import urlsplit - -import requests - -# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916 -def get_istio_auth_session(url: str, username: str, password: str) -> dict: - """ - Determine if the specified URL is secured by Dex and try to obtain a session cookie. - WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported - (we default default to using `staticPasswords` if both are enabled) - - :param url: Kubeflow server URL, including protocol - :param username: Dex `staticPasswords` or `LDAP` username - :param password: Dex `staticPasswords` or `LDAP` password - :return: auth session information - """ - # define the default return object - auth_session = { - "endpoint_url": url, # KF endpoint URL - "redirect_url": None, # KF redirect URL, if applicable - "dex_login_url": None, # Dex login URL (for POST of credentials) - "is_secured": None, # True if KF endpoint is secured - "session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2" - } - - # use a persistent session (for cookies) - with requests.Session() as s: - - ################ - # Determine if Endpoint is Secured - ################ - resp = s.get(url, allow_redirects=True) - if resp.status_code != 200: - raise RuntimeError( - f"HTTP status code '{resp.status_code}' for GET against: {url}" - ) - - auth_session["redirect_url"] = resp.url - - # if we were NOT redirected, then the endpoint is UNSECURED - if len(resp.history) == 0: - auth_session["is_secured"] = False - return auth_session - else: - auth_session["is_secured"] = True - - ################ - # Get Dex Login URL - ################ - redirect_url_obj = urlsplit(auth_session["redirect_url"]) - - # if we are at `/auth?=xxxx` path, we need to select an auth type - if re.search(r"/auth$", redirect_url_obj.path): - # default to "staticPasswords" auth type - redirect_url_obj = redirect_url_obj._replace( - path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path) - ) - - # if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST) - if re.search(r"/auth/.*/login$", redirect_url_obj.path): - auth_session["dex_login_url"] = redirect_url_obj.geturl() - - # else, we need to be redirected to the actual login page - else: - # this GET should redirect us to the `/auth/xxxx/login` path - resp = s.get(redirect_url_obj.geturl(), allow_redirects=True) - if resp.status_code != 200: - raise RuntimeError( - f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}" - ) - - # set the login url - auth_session["dex_login_url"] = resp.url - - ################ - # Attempt Dex Login - ################ - resp = s.post( - auth_session["dex_login_url"], - data={"login": username, "password": password}, - allow_redirects=True - ) - if len(resp.history) == 0: - raise RuntimeError( - f"Login credentials were probably invalid - " - f"No redirect after POST to: {auth_session['dex_login_url']}" - ) - - # store the session cookies in a "key1=value1; key2=value2" string - auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies]) - - return auth_session \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py b/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py deleted file mode 100644 index 3c7c0dfdc..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py +++ /dev/null @@ -1,19 +0,0 @@ -import os -import requests - -from typing import TypedDict - -def retrieve_namespaces(host: str, auth_session: TypedDict) -> str: - workgroup_endpoint = os.path.join(host, "api/workgroup/env-info") - - cookies = {} - cookie_tokens = auth_session["session_cookie"].split("=") - print(cookie_tokens[0]) - cookies[cookie_tokens[0]]=cookie_tokens[1] - resp = requests.get(workgroup_endpoint, cookies=cookies) - if resp.status_code != 200: - raise RuntimeError( - f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}" - ) - return [ns["namespace"] for ns in resp.json()["namespaces"] if - ns["role"]=="owner"] \ No newline at end of file diff --git a/kubeflow/examples/1.connect-kubeflow/py/mnist.py b/kubeflow/examples/1.connect-kubeflow/py/mnist.py deleted file mode 100644 index fc2911a05..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/mnist.py +++ /dev/null @@ -1,132 +0,0 @@ -from __future__ import print_function - -import time -import kfp_server_api -import os -import requests -import string -import random -import json -from kfp_server_api.rest import ApiException -from pprint import pprint -from kfp_login import get_istio_auth_session -from kfp_namespace import retrieve_namespaces - -host = "https://ai4edu.thu01.footprint-ai.com" -username = "thu02" -password = "M*$3sNF7" - -auth_session = get_istio_auth_session( - url=host, - username=username, - password=password - ) - -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. - -# Configure API key authorization: Bearer -configuration = kfp_server_api.Configuration( - host = os.path.join(host, "pipeline"), -) -configuration.debug = True - -namespaces = retrieve_namespaces(host, auth_session) -#print("available namespace: {}".format(namespaces)) - -def random_suffix() -> string: - return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) - -# Enter a context with an instance of the API client -with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: - # Create an instance of the Experiment API class - experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) - name="experiment-" + random_suffix() - description="This is a experiment for mnist." - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey( - type=kfp_server_api.models.ApiResourceType.NAMESPACE, - id=resource_reference_key_id - ), - relationship=kfp_server_api.models.ApiRelationship.OWNER - )] - body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. - try: - # Creates a new experiment. - experiment_api_response = experiment_api_instance.create_experiment(body) - experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) - - # Create an instance of the pipeline API class - api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) - uploadfile='pipelines/mnist_pipeline.yaml' - name='pipeline-' + random_suffix() - description="This is a mnist pipline." - try: - pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) - pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) - - # Create an instance of the run API class - run_api_instance = kfp_server_api.RunServiceApi(api_client) - display_name = 'mnist' + random_suffix() - description = "This is a mnist run." - pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) - resource_reference_key_id = namespaces[0] - resource_references=[kfp_server_api.models.ApiResourceReference( - key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), - relationship=kfp_server_api.models.ApiRelationship.OWNER )] - body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | - try: - # Creates a new run. - run_api_response = run_api_instance.create_run(body) - run_id = run_api_response.run.id # str | The ID of the run to be retrieved. - except ApiException as e: - print("Exception when calling RunServiceApi->create_run: %s\n" % e) - - Completed_flag = False - polling_interval = 10 # Time in seconds between polls - - while not Completed_flag: - try: - time.sleep(1) - # Finds a specific run by ID. - api_instance = run_api_instance.get_run(run_id) - output = api_instance.pipeline_runtime.workflow_manifest - output = json.loads(output) - - try: - nodes = output['status']['nodes'] - conditions = output['status']['conditions'] # Comfirm completion. - - except KeyError: - nodes = {} - conditions = [] - - output_value = None - Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False - - except ApiException as e: - print("Exception when calling RunServiceApi->get_run: %s\n" % e) - break - - if not Completed_flag: - print("Pipeline is still running. Waiting...") - time.sleep(polling_interval-1) - - for node_id, node in nodes.items(): - if 'inputs' in node and 'parameters' in node['inputs']: - for parameter in node['inputs']['parameters']: - if parameter['name'] == 'client-last_accuracy': - output_value = parameter['value'] - - if output_value is not None: - print(f"fl Accuracy: {output_value}") - else: - print("Parameter not found.") - print(nodes) diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml deleted file mode 100644 index 11f53462f..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml +++ /dev/null @@ -1,651 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Workflow -metadata: - generateName: fl-test- - annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2024-01-02T05:53:41.650368', - pipelines.kubeflow.org/pipeline_spec: '{"inputs": [{"default": "kubeflow-user-thu01", - "name": "namespace", "optional": true}], "name": "FL test"}'} - labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} -spec: - entrypoint: fl-test - templates: - - name: client - container: - args: [--batch, '1', '----output-paths', /tmp/outputs/last_accuracy/data] - command: - - sh - - -c - - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install - --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - "def client(batch):\n import json\n import requests\n import time\n\ - \ import pandas as pd\n import numpy as np\n import tensorflow as\ - \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ - \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ - \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ - \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ - \ tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import\ - \ Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras\ - \ import backend as K\n\n normal_url='https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'\ - \ \n abnormal_url='https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download'\n\ - \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ - \ num_features = len(normal_data.columns)\n print(num_features)\n \ - \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ - \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ - \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ - \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ - \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ - \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ - \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ - \n input_shape = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n\ - \ @staticmethod\n def build(shape, classes):\n model\ - \ = Sequential()\n model.add(LSTM(units=64, input_shape=input_shape,\ - \ return_sequences=True))\n model.add(Dropout(0.2))\n \ - \ model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n \ - \ model.add(Dense(units=num_classes, activation='softmax'))\n\n \ - \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ - \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ - \ #The client should have its own data, not like this. It's a lazy method.\n\ - \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ - \n #seperate shard into data and labels lists\n data, label\ - \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ - \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ - \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ - \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ - \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ - \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ - \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ - \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ - \ \n optimizer=optimizer, \n metrics=metrics)\n\ - \n if(comm_round == 0):\n history = client_model.fit(dataset,\ - \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ - \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ - \ test_loss, test_accuracy = client_model.evaluate(dataset)\n \ - \ print(f'Test accuracy: {test_accuracy}')\n\n local_weight = client_model.get_weights()\n\ - \ local_weight = [np.array(w).tolist() for w in local_weight]\n\n \ - \ client_data = {\"local_count\": local_count,'bs': bs, 'local_weight':\ - \ json.dumps(local_weight)}\n\n while True:\n try:\n \ - \ weight = (requests.post(server_url,data=client_data))\n\n \ - \ if weight.status_code == 200:\n print(f\"\ - exist\")\n\n break\n else:\n \ - \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ - \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ - \ data = weight.json()\n avg_weight = data.get('result')\n \ - \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ - \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ - \ \n try:\n response = requests.get(shutdown_url)\n except\ - \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ - \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ - \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ - \ str:\n if isinstance(float_value, str):\n return float_value\n\ - \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ - \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ - \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ - _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ - --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ - _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ - \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ - _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ - \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ - \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ - \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" - image: tensorflow/tensorflow - resources: - limits: {cpu: '0.2'} - requests: {cpu: '0.2'} - outputs: - parameters: - - name: client-last_accuracy - valueFrom: {path: /tmp/outputs/last_accuracy/data} - artifacts: - - {name: client-last_accuracy, path: /tmp/outputs/last_accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": - "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 - python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' - || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def client(batch):\n import json\n import requests\n import time\n import - pandas as pd\n import numpy as np\n import tensorflow as tf\n from - tensorflow.keras.models import Sequential\n from tensorflow.keras.layers - import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from - tensorflow.keras.layers import Activation\n from tensorflow.keras.layers - import Flatten\n from tensorflow.keras.layers import Dense\n from - tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import - Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras - import backend as K\n\n normal_url=''https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'' - \n abnormal_url=''https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download''\n normal_data - = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features - = len(normal_data.columns)\n print(num_features)\n normal_label = - np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, - 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label - = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data - = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), - num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data - = list(zip(data, data_label))\n data_length=len(full_data)\n\n input_shape - = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n @staticmethod\n def - build(shape, classes):\n model = Sequential()\n model.add(LSTM(units=64, - input_shape=input_shape, return_sequences=True))\n model.add(Dropout(0.2))\n model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n model.add(Dense(units=num_classes, - activation=''softmax''))\n\n return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] - #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] - #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data - len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate - shard into data and labels lists\n data, label = zip(*data_shard)\n dataset - = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return - dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs - = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics - = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for - comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model - = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, - \n metrics=metrics)\n\n if(comm_round == 0):\n history - = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history - = client_model.fit(dataset, epochs=5, verbose=1)\n\n test_loss, test_accuracy - = client_model.evaluate(dataset)\n print(f''Test accuracy: {test_accuracy}'')\n\n local_weight - = client_model.get_weights()\n local_weight = [np.array(w).tolist() - for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': - bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight - = (requests.post(server_url,data=client_data))\n\n if weight.status_code - == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server - error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not - exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight - = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight - = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response - = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already - shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef - _serialize_float(float_value: float) -> str:\n if isinstance(float_value, - str):\n return float_value\n if not isinstance(float_value, (float, - int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of - float.''.format(\n str(float_value), str(type(float_value))))\n return - str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', - description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, - required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", - dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files - = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers - = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except - OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], - "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": - "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": - "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": - "1"}'} - - name: client-2 - container: - args: [--batch, '2', '----output-paths', /tmp/outputs/last_accuracy/data] - command: - - sh - - -c - - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install - --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - "def client(batch):\n import json\n import requests\n import time\n\ - \ import pandas as pd\n import numpy as np\n import tensorflow as\ - \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ - \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ - \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ - \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ - \ tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import\ - \ Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras\ - \ import backend as K\n\n normal_url='https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'\ - \ \n abnormal_url='https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download'\n\ - \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ - \ num_features = len(normal_data.columns)\n print(num_features)\n \ - \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ - \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ - \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ - \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ - \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ - \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ - \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ - \n input_shape = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n\ - \ @staticmethod\n def build(shape, classes):\n model\ - \ = Sequential()\n model.add(LSTM(units=64, input_shape=input_shape,\ - \ return_sequences=True))\n model.add(Dropout(0.2))\n \ - \ model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n \ - \ model.add(Dense(units=num_classes, activation='softmax'))\n\n \ - \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ - \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ - \ #The client should have its own data, not like this. It's a lazy method.\n\ - \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ - \n #seperate shard into data and labels lists\n data, label\ - \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ - \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ - \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ - \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ - \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ - \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ - \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ - \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ - \ \n optimizer=optimizer, \n metrics=metrics)\n\ - \n if(comm_round == 0):\n history = client_model.fit(dataset,\ - \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ - \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ - \ test_loss, test_accuracy = client_model.evaluate(dataset)\n \ - \ print(f'Test accuracy: {test_accuracy}')\n\n local_weight = client_model.get_weights()\n\ - \ local_weight = [np.array(w).tolist() for w in local_weight]\n\n \ - \ client_data = {\"local_count\": local_count,'bs': bs, 'local_weight':\ - \ json.dumps(local_weight)}\n\n while True:\n try:\n \ - \ weight = (requests.post(server_url,data=client_data))\n\n \ - \ if weight.status_code == 200:\n print(f\"\ - exist\")\n\n break\n else:\n \ - \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ - \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ - \ data = weight.json()\n avg_weight = data.get('result')\n \ - \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ - \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ - \ \n try:\n response = requests.get(shutdown_url)\n except\ - \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ - \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ - \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ - \ str:\n if isinstance(float_value, str):\n return float_value\n\ - \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ - \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ - \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ - _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ - --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ - _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ - \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ - _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ - \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ - \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ - \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" - image: tensorflow/tensorflow - resources: - limits: {cpu: '0.2'} - requests: {cpu: '0.2'} - outputs: - artifacts: - - {name: client-2-last_accuracy, path: /tmp/outputs/last_accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": - "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 - python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' - || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def client(batch):\n import json\n import requests\n import time\n import - pandas as pd\n import numpy as np\n import tensorflow as tf\n from - tensorflow.keras.models import Sequential\n from tensorflow.keras.layers - import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from - tensorflow.keras.layers import Activation\n from tensorflow.keras.layers - import Flatten\n from tensorflow.keras.layers import Dense\n from - tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import - Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras - import backend as K\n\n normal_url=''https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'' - \n abnormal_url=''https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download''\n normal_data - = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features - = len(normal_data.columns)\n print(num_features)\n normal_label = - np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, - 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label - = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data - = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), - num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data - = list(zip(data, data_label))\n data_length=len(full_data)\n\n input_shape - = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n @staticmethod\n def - build(shape, classes):\n model = Sequential()\n model.add(LSTM(units=64, - input_shape=input_shape, return_sequences=True))\n model.add(Dropout(0.2))\n model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n model.add(Dense(units=num_classes, - activation=''softmax''))\n\n return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] - #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] - #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data - len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate - shard into data and labels lists\n data, label = zip(*data_shard)\n dataset - = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return - dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs - = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics - = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for - comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model - = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, - \n metrics=metrics)\n\n if(comm_round == 0):\n history - = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history - = client_model.fit(dataset, epochs=5, verbose=1)\n\n test_loss, test_accuracy - = client_model.evaluate(dataset)\n print(f''Test accuracy: {test_accuracy}'')\n\n local_weight - = client_model.get_weights()\n local_weight = [np.array(w).tolist() - for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': - bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight - = (requests.post(server_url,data=client_data))\n\n if weight.status_code - == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server - error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not - exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight - = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight - = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response - = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already - shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef - _serialize_float(float_value: float) -> str:\n if isinstance(float_value, - str):\n return float_value\n if not isinstance(float_value, (float, - int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of - float.''.format(\n str(float_value), str(type(float_value))))\n return - str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', - description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, - required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", - dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files - = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers - = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except - OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], - "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": - "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": - "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": - "2"}'} - - name: delete-service - resource: - action: delete - flags: [--wait=false] - manifest: | - apiVersion: v1 - kind: Service - metadata: - name: http-service - spec: - ports: - - port: 80 - protocol: TCP - targetPort: 8080 - selector: - app: http-service - type: NodePort - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - - name: fl-test - dag: - tasks: - - {name: client, template: client} - - {name: client-2, template: client-2} - - name: delete-service - template: delete-service - dependencies: [server] - - {name: http-service, template: http-service} - - name: server - template: server - dependencies: [http-service] - - name: show-results - template: show-results - dependencies: [client] - arguments: - parameters: - - {name: client-last_accuracy, value: '{{tasks.client.outputs.parameters.client-last_accuracy}}'} - - name: http-service - resource: - action: create - manifest: | - apiVersion: v1 - kind: Service - metadata: - name: http-service - spec: - ports: - - port: 5000 - protocol: TCP - targetPort: 8080 - selector: - app: http-service - outputs: - parameters: - - name: http-service-manifest - valueFrom: {jsonPath: '{}'} - - name: http-service-name - valueFrom: {jsonPath: '{.metadata.name}'} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - - name: server - container: - args: [] - command: - - sh - - -c - - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - 'flask' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install - --quiet --no-warn-script-location 'flask' 'pandas' --user) && "$0" "$@" - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - "def server():\n import json\n import pandas as pd\n import numpy\ - \ as np\n import pickle\n import threading\n import time\n import\ - \ tensorflow as tf\n from flask import Flask, jsonify,request\n import\ - \ os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list\ - \ = []\n global_value = { #Share variable\n 'last_run_statue'\ - \ : False, #last run finish or not\n 'data_statue' : None,\ - \ #global_count finish or not\n 'global_count' : None,\n\ - \ 'scale_statue' : None,\n 'weight_statue'\ - \ : None,\n 'average_weights' : None,\n \ - \ 'shutdown' : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n \ - \ init_lock = threading.Lock()\n clients_local_count_lock = threading.Lock()\n\ - \ scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock\ - \ = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n\ - \ def before_request():\n print('get request')\n\n @app.route('/data',\ - \ methods=['POST'])\n def flask_server():\n with init_lock: #check\ - \ last run is finish and init varible\n\n while True:\n\n \ - \ if(len(clients_local_count)==0 and global_value['last_run_statue']\ - \ == False):#init the variable by first client enter\n \ - \ global_value['last_run_statue'] = True\n global_value['data_statue']\ - \ = False\n global_value['scale_statue'] = False\n \ - \ global_value['weight_statue'] = False\n \ - \ break\n\n elif(global_value['last_run_statue'] == True):\n\ - \ break\n time.sleep(3)\n\n local_count\ - \ = int(request.form.get('local_count')) #get data\n bs =\ - \ int(request.form.get('bs'))\n local_weight = json.loads(request.form.get('local_weight'))\n\ - \ local_weight = [np.array(lst) for lst in local_weight]\n\n \ - \ def scale_model_weights(weight, scalar):\n weight_final = []\n\ - \ steps = len(weight)\n for i in range(steps):\n \ - \ weight_final.append(scalar * weight[i])\n return\ - \ weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n \ - \ avg_grad = list()\n #get the average grad accross all\ - \ client gradients\n for grad_list_tuple in zip(*scaled_weight_list):\n\ - \ layer_mean = tf.math.reduce_sum(grad_list_tuple, axis=0)\n\ - \ avg_grad.append(layer_mean)\n\n return avg_grad\n\ - \n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\ - \n with scaled_local_weight_list_lock:\n while True:\n\n\ - \ if (len(clients_local_count) == NUM_OF_CLIENTS and global_value['data_statue']\ - \ != True):\n global_value['last_run_statue'] = False\n\ - \ sum_of_local_count=sum(clients_local_count)\n\n \ - \ global_value['global_count'] = sum_of_local_count \n\n\ - \ scaling_factor=local_count/global_value['global_count']\n\ - \ scaled_weights = scale_model_weights(local_weight, scaling_factor)\n\ - \ scaled_local_weight_list.append(scaled_weights)\n\n \ - \ global_value['scale_statue'] = True \n \ - \ global_value['data_statue'] = True\n break\n \ - \ elif (global_value['data_statue'] == True and global_value['scale_statue']\ - \ == True):\n scaling_factor=local_count/global_value['global_count']\n\ - \ scaled_weights =scale_model_weights(local_weight, scaling_factor)\n\ - \ scaled_local_weight_list.append(scaled_weights)\n\n \ - \ break\n time.sleep(1)\n\n with cal_weight_lock:\n\ - \n while True:\n if(len(scaled_local_weight_list)\ - \ == NUM_OF_CLIENTS and global_value['weight_statue'] != True):\n\n \ - \ global_value['average_weights'] = sum_scaled_weights(scaled_local_weight_list)\n\ - \ global_value['weight_statue'] = True\n \ - \ global_value['average_weights'] = json.dumps([np.array(w).tolist()\ - \ for w in global_value['average_weights']])\n\n break\n\ - \n elif(global_value['weight_statue'] == True):\n\n \ - \ break\n\n time.sleep(1)\n\n clients_local_count.clear()\n\ - \ scaled_local_weight_list.clear()\n\n return jsonify({'result':\ - \ (global_value['average_weights'])})\n\n @app.route('/shutdown', methods=['GET'])\n\ - \ def shutdown_server():\n global_value['shutdown'] +=1 \n \ - \ with shutdown_lock:\n while True:\n if(global_value['shutdown']\ - \ == NUM_OF_CLIENTS):\n os._exit(0)\n \ - \ return 'Server shutting down...'\n time.sleep(1)\n\n \ - \ app.run(host=\"0.0.0.0\", port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Server',\ - \ description='')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs =\ - \ server(**_parsed_args)\n" - image: tensorflow/tensorflow - ports: - - {containerPort: 8080, name: my-port} - resources: - limits: {cpu: '0.2'} - requests: {cpu: '0.2'} - metadata: - labels: - app: http-service - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": [], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 python3 - -m pip install --quiet --no-warn-script-location ''flask'' ''pandas'' || - PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - ''flask'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def server():\n import json\n import pandas as pd\n import numpy - as np\n import pickle\n import threading\n import time\n import - tensorflow as tf\n from flask import Flask, jsonify,request\n import - os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list - = []\n global_value = { #Share variable\n ''last_run_statue'' - : False, #last run finish or not\n ''data_statue'' : - None, #global_count finish or not\n ''global_count'' - : None,\n ''scale_statue'' : None,\n ''weight_statue'' - : None,\n ''average_weights'' : None,\n ''shutdown'' - : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n init_lock = threading.Lock()\n clients_local_count_lock - = threading.Lock()\n scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock - = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n def - before_request():\n print(''get request'')\n\n @app.route(''/data'', - methods=[''POST''])\n def flask_server():\n with init_lock: #check - last run is finish and init varible\n\n while True:\n\n if(len(clients_local_count)==0 - and global_value[''last_run_statue''] == False):#init the variable by first - client enter\n global_value[''last_run_statue''] = True\n global_value[''data_statue''] - = False\n global_value[''scale_statue''] = False\n global_value[''weight_statue''] - = False\n break\n\n elif(global_value[''last_run_statue''] - == True):\n break\n time.sleep(3)\n\n local_count - = int(request.form.get(''local_count'')) #get data\n bs - = int(request.form.get(''bs''))\n local_weight = json.loads(request.form.get(''local_weight''))\n local_weight - = [np.array(lst) for lst in local_weight]\n\n def scale_model_weights(weight, - scalar):\n weight_final = []\n steps = len(weight)\n for - i in range(steps):\n weight_final.append(scalar * weight[i])\n return - weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n avg_grad - = list()\n #get the average grad accross all client gradients\n for - grad_list_tuple in zip(*scaled_weight_list):\n layer_mean - = tf.math.reduce_sum(grad_list_tuple, axis=0)\n avg_grad.append(layer_mean)\n\n return - avg_grad\n\n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\n with - scaled_local_weight_list_lock:\n while True:\n\n if - (len(clients_local_count) == NUM_OF_CLIENTS and global_value[''data_statue''] - != True):\n global_value[''last_run_statue''] = False\n sum_of_local_count=sum(clients_local_count)\n\n global_value[''global_count''] - = sum_of_local_count \n\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights - = scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n global_value[''scale_statue''] - = True \n global_value[''data_statue''] = True\n break\n elif - (global_value[''data_statue''] == True and global_value[''scale_statue''] - == True):\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights - =scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n break\n time.sleep(1)\n\n with - cal_weight_lock:\n\n while True:\n if(len(scaled_local_weight_list) - == NUM_OF_CLIENTS and global_value[''weight_statue''] != True):\n\n global_value[''average_weights''] - = sum_scaled_weights(scaled_local_weight_list)\n global_value[''weight_statue''] - = True\n global_value[''average_weights''] = json.dumps([np.array(w).tolist() - for w in global_value[''average_weights'']])\n\n break\n\n elif(global_value[''weight_statue''] - == True):\n\n break\n\n time.sleep(1)\n\n clients_local_count.clear()\n scaled_local_weight_list.clear()\n\n return - jsonify({''result'': (global_value[''average_weights''])})\n\n @app.route(''/shutdown'', - methods=[''GET''])\n def shutdown_server():\n global_value[''shutdown''] - +=1 \n with shutdown_lock:\n while True:\n if(global_value[''shutdown''] - == NUM_OF_CLIENTS):\n os._exit(0)\n return - ''Server shutting down...''\n time.sleep(1)\n\n app.run(host=\"0.0.0.0\", - port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Server'', - description='''')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs - = server(**_parsed_args)\n"], "image": "tensorflow/tensorflow"}}, "name": - "Server"}', pipelines.kubeflow.org/component_ref: '{}'} - - name: show-results - container: - args: [--test-acc, '{{inputs.parameters.client-last_accuracy}}', '----output-paths', - /tmp/outputs/test_accuracy/data] - command: - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - | - def show_results(test_acc): - return([test_acc]) - - def _serialize_float(float_value: float) -> str: - if isinstance(float_value, str): - return float_value - if not isinstance(float_value, (float, int)): - raise TypeError('Value "{}" has type "{}" instead of float.'.format( - str(float_value), str(type(float_value)))) - return str(float_value) - - import argparse - _parser = argparse.ArgumentParser(prog='Show results', description='') - _parser.add_argument("--test-acc", dest="test_acc", type=float, required=True, default=argparse.SUPPRESS) - _parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=1) - _parsed_args = vars(_parser.parse_args()) - _output_files = _parsed_args.pop("_output_paths", []) - - _outputs = show_results(**_parsed_args) - - _output_serializers = [ - _serialize_float, - - ] - - import os - for idx, output_file in enumerate(_output_files): - try: - os.makedirs(os.path.dirname(output_file)) - except OSError: - pass - with open(output_file, 'w') as f: - f.write(_output_serializers[idx](_outputs[idx])) - image: python:3.7 - resources: - limits: {cpu: '0.2'} - requests: {cpu: '0.2'} - inputs: - parameters: - - {name: client-last_accuracy} - outputs: - artifacts: - - {name: show-results-test_accuracy, path: /tmp/outputs/test_accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--test-acc", {"inputValue": "test_acc"}, "----output-paths", - {"outputPath": "test_accuracy"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def show_results(test_acc):\n return([test_acc])\n\ndef _serialize_float(float_value: - float) -> str:\n if isinstance(float_value, str):\n return float_value\n if - not isinstance(float_value, (float, int)):\n raise TypeError(''Value - \"{}\" has type \"{}\" instead of float.''.format(\n str(float_value), - str(type(float_value))))\n return str(float_value)\n\nimport argparse\n_parser - = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--test-acc\", - dest=\"test_acc\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", - dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files - = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = show_results(**_parsed_args)\n\n_output_serializers - = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except - OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], - "image": "python:3.7"}}, "inputs": [{"name": "test_acc", "type": "Float"}], - "name": "Show results", "outputs": [{"name": "test_accuracy", "type": "Float"}]}', - pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"test_acc": - "{{inputs.parameters.client-last_accuracy}}"}'} - arguments: - parameters: - - {name: namespace, value: kubeflow-user-thu01} - serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml deleted file mode 100644 index 8381600f3..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml +++ /dev/null @@ -1,639 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Workflow -metadata: - generateName: fl-test- - annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-12-13T03:33:40.267552', - pipelines.kubeflow.org/pipeline_spec: '{"inputs": [{"default": "kubeflow-user-thu01", - "name": "namespace", "optional": true}], "name": "FL test"}'} - labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} -spec: - entrypoint: fl-test - templates: - - name: client - container: - args: [--batch, '1', '----output-paths', /tmp/outputs/last_accuracy/data] - command: - - sh - - -c - - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install - --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - "def client(batch):\n import json\n import requests\n import time\n\ - \ import pandas as pd\n import numpy as np\n import tensorflow as\ - \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ - \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ - \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ - \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ - \ tensorflow.keras.optimizers import SGD\n from tensorflow.keras import\ - \ backend as K\n\n normal_url='https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'\ - \ \n abnormal_url='https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy'\n\ - \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ - \ num_features = len(normal_data.columns)\n print(num_features)\n \ - \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ - \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ - \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ - \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ - \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ - \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ - \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ - \n class SimpleMLP:\n @staticmethod\n def build(shape, classes):\n\ - \ model = Sequential()\n model.add(Conv1D(filters=4,\ - \ kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n\ - \ model.add(Flatten())\n model.add(Dense(8, activation=\"\ - relu\"))\n model.add(Dense(2, activation = 'softmax'))\n\n \ - \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ - \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ - \ #The client should have its own data, not like this. It's a lazy method.\n\ - \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ - \n #seperate shard into data and labels lists\n data, label\ - \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ - \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ - \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ - \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ - \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ - \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ - \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ - \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ - \ \n optimizer=optimizer, \n metrics=metrics)\n\ - \n if(comm_round == 0):\n history = client_model.fit(dataset,\ - \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ - \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ - \ local_weight = client_model.get_weights()\n local_weight =\ - \ [np.array(w).tolist() for w in local_weight]\n\n client_data = {\"\ - local_count\": local_count,'bs': bs, 'local_weight': json.dumps(local_weight)}\n\ - \n while True:\n try:\n weight = (requests.post(server_url,data=client_data))\n\ - \n if weight.status_code == 200:\n print(f\"\ - exist\")\n\n break\n else:\n \ - \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ - \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ - \ data = weight.json()\n avg_weight = data.get('result')\n \ - \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ - \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ - \ \n try:\n response = requests.get(shutdown_url)\n except\ - \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ - \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ - \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ - \ str:\n if isinstance(float_value, str):\n return float_value\n\ - \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ - \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ - \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ - _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ - --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ - _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ - \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ - _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ - \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ - \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ - \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" - image: tensorflow/tensorflow - resources: - limits: {cpu: '0.2'} - requests: {cpu: '0.2'} - outputs: - parameters: - - name: client-last_accuracy - valueFrom: {path: /tmp/outputs/last_accuracy/data} - artifacts: - - {name: client-last_accuracy, path: /tmp/outputs/last_accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": - "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 - python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' - || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def client(batch):\n import json\n import requests\n import time\n import - pandas as pd\n import numpy as np\n import tensorflow as tf\n from - tensorflow.keras.models import Sequential\n from tensorflow.keras.layers - import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from - tensorflow.keras.layers import Activation\n from tensorflow.keras.layers - import Flatten\n from tensorflow.keras.layers import Dense\n from - tensorflow.keras.optimizers import SGD\n from tensorflow.keras import - backend as K\n\n normal_url=''https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'' - \n abnormal_url=''https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy''\n normal_data - = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features - = len(normal_data.columns)\n print(num_features)\n normal_label = - np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, - 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label - = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data - = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), - num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data - = list(zip(data, data_label))\n data_length=len(full_data)\n\n class - SimpleMLP:\n @staticmethod\n def build(shape, classes):\n model - = Sequential()\n model.add(Conv1D(filters=4, kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n model.add(Flatten())\n model.add(Dense(8, - activation=\"relu\"))\n model.add(Dense(2, activation = ''softmax''))\n\n return - model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] - #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] - #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data - len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate - shard into data and labels lists\n data, label = zip(*data_shard)\n dataset - = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return - dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs - = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics - = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for - comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model - = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, - \n metrics=metrics)\n\n if(comm_round == 0):\n history - = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history - = client_model.fit(dataset, epochs=5, verbose=1)\n\n local_weight - = client_model.get_weights()\n local_weight = [np.array(w).tolist() - for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': - bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight - = (requests.post(server_url,data=client_data))\n\n if weight.status_code - == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server - error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not - exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight - = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight - = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response - = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already - shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef - _serialize_float(float_value: float) -> str:\n if isinstance(float_value, - str):\n return float_value\n if not isinstance(float_value, (float, - int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of - float.''.format(\n str(float_value), str(type(float_value))))\n return - str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', - description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, - required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", - dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files - = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers - = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except - OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], - "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": - "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": - "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": - "1"}'} - - name: client-2 - container: - args: [--batch, '2', '----output-paths', /tmp/outputs/last_accuracy/data] - command: - - sh - - -c - - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install - --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - "def client(batch):\n import json\n import requests\n import time\n\ - \ import pandas as pd\n import numpy as np\n import tensorflow as\ - \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ - \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ - \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ - \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ - \ tensorflow.keras.optimizers import SGD\n from tensorflow.keras import\ - \ backend as K\n\n normal_url='https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'\ - \ \n abnormal_url='https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy'\n\ - \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ - \ num_features = len(normal_data.columns)\n print(num_features)\n \ - \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ - \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ - \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ - \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ - \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ - \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ - \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ - \n class SimpleMLP:\n @staticmethod\n def build(shape, classes):\n\ - \ model = Sequential()\n model.add(Conv1D(filters=4,\ - \ kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n\ - \ model.add(Flatten())\n model.add(Dense(8, activation=\"\ - relu\"))\n model.add(Dense(2, activation = 'softmax'))\n\n \ - \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ - \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ - \ #The client should have its own data, not like this. It's a lazy method.\n\ - \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ - \n #seperate shard into data and labels lists\n data, label\ - \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ - \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ - \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ - \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ - \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ - \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ - \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ - \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ - \ \n optimizer=optimizer, \n metrics=metrics)\n\ - \n if(comm_round == 0):\n history = client_model.fit(dataset,\ - \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ - \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ - \ local_weight = client_model.get_weights()\n local_weight =\ - \ [np.array(w).tolist() for w in local_weight]\n\n client_data = {\"\ - local_count\": local_count,'bs': bs, 'local_weight': json.dumps(local_weight)}\n\ - \n while True:\n try:\n weight = (requests.post(server_url,data=client_data))\n\ - \n if weight.status_code == 200:\n print(f\"\ - exist\")\n\n break\n else:\n \ - \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ - \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ - \ data = weight.json()\n avg_weight = data.get('result')\n \ - \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ - \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ - \ \n try:\n response = requests.get(shutdown_url)\n except\ - \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ - \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ - \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ - \ str:\n if isinstance(float_value, str):\n return float_value\n\ - \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ - \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ - \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ - _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ - --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ - _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ - \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ - _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ - \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ - \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ - \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" - image: tensorflow/tensorflow - resources: - limits: {cpu: '0.2'} - requests: {cpu: '0.2'} - outputs: - artifacts: - - {name: client-2-last_accuracy, path: /tmp/outputs/last_accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": - "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 - python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' - || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def client(batch):\n import json\n import requests\n import time\n import - pandas as pd\n import numpy as np\n import tensorflow as tf\n from - tensorflow.keras.models import Sequential\n from tensorflow.keras.layers - import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from - tensorflow.keras.layers import Activation\n from tensorflow.keras.layers - import Flatten\n from tensorflow.keras.layers import Dense\n from - tensorflow.keras.optimizers import SGD\n from tensorflow.keras import - backend as K\n\n normal_url=''https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'' - \n abnormal_url=''https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy''\n normal_data - = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features - = len(normal_data.columns)\n print(num_features)\n normal_label = - np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, - 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label - = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data - = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), - num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data - = list(zip(data, data_label))\n data_length=len(full_data)\n\n class - SimpleMLP:\n @staticmethod\n def build(shape, classes):\n model - = Sequential()\n model.add(Conv1D(filters=4, kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n model.add(Flatten())\n model.add(Dense(8, - activation=\"relu\"))\n model.add(Dense(2, activation = ''softmax''))\n\n return - model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] - #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] - #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data - len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate - shard into data and labels lists\n data, label = zip(*data_shard)\n dataset - = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return - dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs - = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics - = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for - comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model - = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, - \n metrics=metrics)\n\n if(comm_round == 0):\n history - = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history - = client_model.fit(dataset, epochs=5, verbose=1)\n\n local_weight - = client_model.get_weights()\n local_weight = [np.array(w).tolist() - for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': - bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight - = (requests.post(server_url,data=client_data))\n\n if weight.status_code - == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server - error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not - exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight - = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight - = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response - = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already - shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef - _serialize_float(float_value: float) -> str:\n if isinstance(float_value, - str):\n return float_value\n if not isinstance(float_value, (float, - int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of - float.''.format(\n str(float_value), str(type(float_value))))\n return - str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', - description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, - required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", - dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files - = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers - = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except - OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], - "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": - "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": - "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": - "2"}'} - - name: delete-service - resource: - action: delete - flags: [--wait=false] - manifest: | - apiVersion: v1 - kind: Service - metadata: - name: http-service - spec: - ports: - - port: 80 - protocol: TCP - targetPort: 8080 - selector: - app: http-service - type: NodePort - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - - name: fl-test - dag: - tasks: - - {name: client, template: client} - - {name: client-2, template: client-2} - - name: delete-service - template: delete-service - dependencies: [server] - - {name: http-service, template: http-service} - - name: server - template: server - dependencies: [http-service] - - name: show-results - template: show-results - dependencies: [client] - arguments: - parameters: - - {name: client-last_accuracy, value: '{{tasks.client.outputs.parameters.client-last_accuracy}}'} - - name: http-service - resource: - action: create - manifest: | - apiVersion: v1 - kind: Service - metadata: - name: http-service - spec: - ports: - - port: 5000 - protocol: TCP - targetPort: 8080 - selector: - app: http-service - outputs: - parameters: - - name: http-service-manifest - valueFrom: {jsonPath: '{}'} - - name: http-service-name - valueFrom: {jsonPath: '{.metadata.name}'} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - - name: server - container: - args: [] - command: - - sh - - -c - - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - 'flask' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install - --quiet --no-warn-script-location 'flask' 'pandas' --user) && "$0" "$@" - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - "def server():\n import json\n import pandas as pd\n import numpy\ - \ as np\n import pickle\n import threading\n import time\n import\ - \ tensorflow as tf\n from flask import Flask, jsonify,request\n import\ - \ os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list\ - \ = []\n global_value = { #Share variable\n 'last_run_statue'\ - \ : False, #last run finish or not\n 'data_statue' : None,\ - \ #global_count finish or not\n 'global_count' : None,\n\ - \ 'scale_statue' : None,\n 'weight_statue'\ - \ : None,\n 'average_weights' : None,\n \ - \ 'shutdown' : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n \ - \ init_lock = threading.Lock()\n clients_local_count_lock = threading.Lock()\n\ - \ scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock\ - \ = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n\ - \ def before_request():\n print('get request')\n\n @app.route('/data',\ - \ methods=['POST'])\n def flask_server():\n with init_lock: #check\ - \ last run is finish and init varible\n\n while True:\n\n \ - \ if(len(clients_local_count)==0 and global_value['last_run_statue']\ - \ == False):#init the variable by first client enter\n \ - \ global_value['last_run_statue'] = True\n global_value['data_statue']\ - \ = False\n global_value['scale_statue'] = False\n \ - \ global_value['weight_statue'] = False\n \ - \ break\n\n elif(global_value['last_run_statue'] == True):\n\ - \ break\n time.sleep(3)\n\n local_count\ - \ = int(request.form.get('local_count')) #get data\n bs =\ - \ int(request.form.get('bs'))\n local_weight = json.loads(request.form.get('local_weight'))\n\ - \ local_weight = [np.array(lst) for lst in local_weight]\n\n \ - \ def scale_model_weights(weight, scalar):\n weight_final = []\n\ - \ steps = len(weight)\n for i in range(steps):\n \ - \ weight_final.append(scalar * weight[i])\n return\ - \ weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n \ - \ avg_grad = list()\n #get the average grad accross all\ - \ client gradients\n for grad_list_tuple in zip(*scaled_weight_list):\n\ - \ layer_mean = tf.math.reduce_sum(grad_list_tuple, axis=0)\n\ - \ avg_grad.append(layer_mean)\n\n return avg_grad\n\ - \n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\ - \n with scaled_local_weight_list_lock:\n while True:\n\n\ - \ if (len(clients_local_count) == NUM_OF_CLIENTS and global_value['data_statue']\ - \ != True):\n global_value['last_run_statue'] = False\n\ - \ sum_of_local_count=sum(clients_local_count)\n\n \ - \ global_value['global_count'] = sum_of_local_count \n\n\ - \ scaling_factor=local_count/global_value['global_count']\n\ - \ scaled_weights = scale_model_weights(local_weight, scaling_factor)\n\ - \ scaled_local_weight_list.append(scaled_weights)\n\n \ - \ global_value['scale_statue'] = True \n \ - \ global_value['data_statue'] = True\n break\n \ - \ elif (global_value['data_statue'] == True and global_value['scale_statue']\ - \ == True):\n scaling_factor=local_count/global_value['global_count']\n\ - \ scaled_weights =scale_model_weights(local_weight, scaling_factor)\n\ - \ scaled_local_weight_list.append(scaled_weights)\n\n \ - \ break\n time.sleep(1)\n\n with cal_weight_lock:\n\ - \n while True:\n if(len(scaled_local_weight_list)\ - \ == NUM_OF_CLIENTS and global_value['weight_statue'] != True):\n\n \ - \ global_value['average_weights'] = sum_scaled_weights(scaled_local_weight_list)\n\ - \ global_value['weight_statue'] = True\n \ - \ global_value['average_weights'] = json.dumps([np.array(w).tolist()\ - \ for w in global_value['average_weights']])\n\n break\n\ - \n elif(global_value['weight_statue'] == True):\n\n \ - \ break\n\n time.sleep(1)\n\n clients_local_count.clear()\n\ - \ scaled_local_weight_list.clear()\n\n return jsonify({'result':\ - \ (global_value['average_weights'])})\n\n @app.route('/shutdown', methods=['GET'])\n\ - \ def shutdown_server():\n global_value['shutdown'] +=1 \n \ - \ with shutdown_lock:\n while True:\n if(global_value['shutdown']\ - \ == NUM_OF_CLIENTS):\n os._exit(0)\n \ - \ return 'Server shutting down...'\n time.sleep(1)\n\n \ - \ app.run(host=\"0.0.0.0\", port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Server',\ - \ description='')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs =\ - \ server(**_parsed_args)\n" - image: tensorflow/tensorflow - ports: - - {containerPort: 8080, name: my-port} - resources: - limits: {cpu: '0.2'} - requests: {cpu: '0.2'} - metadata: - labels: - app: http-service - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": [], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 python3 - -m pip install --quiet --no-warn-script-location ''flask'' ''pandas'' || - PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location - ''flask'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def server():\n import json\n import pandas as pd\n import numpy - as np\n import pickle\n import threading\n import time\n import - tensorflow as tf\n from flask import Flask, jsonify,request\n import - os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list - = []\n global_value = { #Share variable\n ''last_run_statue'' - : False, #last run finish or not\n ''data_statue'' : - None, #global_count finish or not\n ''global_count'' - : None,\n ''scale_statue'' : None,\n ''weight_statue'' - : None,\n ''average_weights'' : None,\n ''shutdown'' - : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n init_lock = threading.Lock()\n clients_local_count_lock - = threading.Lock()\n scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock - = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n def - before_request():\n print(''get request'')\n\n @app.route(''/data'', - methods=[''POST''])\n def flask_server():\n with init_lock: #check - last run is finish and init varible\n\n while True:\n\n if(len(clients_local_count)==0 - and global_value[''last_run_statue''] == False):#init the variable by first - client enter\n global_value[''last_run_statue''] = True\n global_value[''data_statue''] - = False\n global_value[''scale_statue''] = False\n global_value[''weight_statue''] - = False\n break\n\n elif(global_value[''last_run_statue''] - == True):\n break\n time.sleep(3)\n\n local_count - = int(request.form.get(''local_count'')) #get data\n bs - = int(request.form.get(''bs''))\n local_weight = json.loads(request.form.get(''local_weight''))\n local_weight - = [np.array(lst) for lst in local_weight]\n\n def scale_model_weights(weight, - scalar):\n weight_final = []\n steps = len(weight)\n for - i in range(steps):\n weight_final.append(scalar * weight[i])\n return - weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n avg_grad - = list()\n #get the average grad accross all client gradients\n for - grad_list_tuple in zip(*scaled_weight_list):\n layer_mean - = tf.math.reduce_sum(grad_list_tuple, axis=0)\n avg_grad.append(layer_mean)\n\n return - avg_grad\n\n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\n with - scaled_local_weight_list_lock:\n while True:\n\n if - (len(clients_local_count) == NUM_OF_CLIENTS and global_value[''data_statue''] - != True):\n global_value[''last_run_statue''] = False\n sum_of_local_count=sum(clients_local_count)\n\n global_value[''global_count''] - = sum_of_local_count \n\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights - = scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n global_value[''scale_statue''] - = True \n global_value[''data_statue''] = True\n break\n elif - (global_value[''data_statue''] == True and global_value[''scale_statue''] - == True):\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights - =scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n break\n time.sleep(1)\n\n with - cal_weight_lock:\n\n while True:\n if(len(scaled_local_weight_list) - == NUM_OF_CLIENTS and global_value[''weight_statue''] != True):\n\n global_value[''average_weights''] - = sum_scaled_weights(scaled_local_weight_list)\n global_value[''weight_statue''] - = True\n global_value[''average_weights''] = json.dumps([np.array(w).tolist() - for w in global_value[''average_weights'']])\n\n break\n\n elif(global_value[''weight_statue''] - == True):\n\n break\n\n time.sleep(1)\n\n clients_local_count.clear()\n scaled_local_weight_list.clear()\n\n return - jsonify({''result'': (global_value[''average_weights''])})\n\n @app.route(''/shutdown'', - methods=[''GET''])\n def shutdown_server():\n global_value[''shutdown''] - +=1 \n with shutdown_lock:\n while True:\n if(global_value[''shutdown''] - == NUM_OF_CLIENTS):\n os._exit(0)\n return - ''Server shutting down...''\n time.sleep(1)\n\n app.run(host=\"0.0.0.0\", - port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Server'', - description='''')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs - = server(**_parsed_args)\n"], "image": "tensorflow/tensorflow"}}, "name": - "Server"}', pipelines.kubeflow.org/component_ref: '{}'} - - name: show-results - container: - args: [--test-acc, '{{inputs.parameters.client-last_accuracy}}', '----output-paths', - /tmp/outputs/test_accuracy/data] - command: - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - | - def show_results(test_acc): - return([test_acc]) - - def _serialize_float(float_value: float) -> str: - if isinstance(float_value, str): - return float_value - if not isinstance(float_value, (float, int)): - raise TypeError('Value "{}" has type "{}" instead of float.'.format( - str(float_value), str(type(float_value)))) - return str(float_value) - - import argparse - _parser = argparse.ArgumentParser(prog='Show results', description='') - _parser.add_argument("--test-acc", dest="test_acc", type=float, required=True, default=argparse.SUPPRESS) - _parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=1) - _parsed_args = vars(_parser.parse_args()) - _output_files = _parsed_args.pop("_output_paths", []) - - _outputs = show_results(**_parsed_args) - - _output_serializers = [ - _serialize_float, - - ] - - import os - for idx, output_file in enumerate(_output_files): - try: - os.makedirs(os.path.dirname(output_file)) - except OSError: - pass - with open(output_file, 'w') as f: - f.write(_output_serializers[idx](_outputs[idx])) - image: python:3.7 - resources: - limits: {cpu: '0.2'} - requests: {cpu: '0.2'} - inputs: - parameters: - - {name: client-last_accuracy} - outputs: - artifacts: - - {name: show-results-test_accuracy, path: /tmp/outputs/test_accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--test-acc", {"inputValue": "test_acc"}, "----output-paths", - {"outputPath": "test_accuracy"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def show_results(test_acc):\n return([test_acc])\n\ndef _serialize_float(float_value: - float) -> str:\n if isinstance(float_value, str):\n return float_value\n if - not isinstance(float_value, (float, int)):\n raise TypeError(''Value - \"{}\" has type \"{}\" instead of float.''.format(\n str(float_value), - str(type(float_value))))\n return str(float_value)\n\nimport argparse\n_parser - = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--test-acc\", - dest=\"test_acc\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", - dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files - = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = show_results(**_parsed_args)\n\n_output_serializers - = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except - OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], - "image": "python:3.7"}}, "inputs": [{"name": "test_acc", "type": "Float"}], - "name": "Show results", "outputs": [{"name": "test_accuracy", "type": "Float"}]}', - pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"test_acc": - "{{inputs.parameters.client-last_accuracy}}"}'} - arguments: - parameters: - - {name: namespace, value: kubeflow-user-thu01} - serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml deleted file mode 100644 index b8f353c80..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml +++ /dev/null @@ -1,211 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Workflow -metadata: - generateName: mnist-pipeline- - annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-12-26T13:06:02.352865', - pipelines.kubeflow.org/pipeline_spec: '{"description": "A pipeline to train a - model on mnist dataset and start a tensorboard.", "name": "mnist pipeline"}'} - labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} -spec: - entrypoint: mnist-pipeline - templates: - - name: create-tensorboard-visualization - container: - args: [] - command: - - sh - - -ex - - -c - - | - log_dir="$0" - output_metadata_path="$1" - pod_template_spec="$2" - image="$3" - - mkdir -p "$(dirname "$output_metadata_path")" - - echo ' - { - "outputs" : [{ - "type": "tensorboard", - "source": "'"$log_dir"'", - "image": "'"$image"'", - "pod_template_spec": '"$pod_template_spec"' - }] - } - ' >"$output_metadata_path" - - volume://mypvc/logs - - /tmp/outputs/mlpipeline-ui-metadata/data - - '{"spec": {"containers": [{"volumeMounts": [{"mountPath": "/data", "name": - "mypvc"}], "resources": {"requests": {"cpu": "250m"}, "limits": {"cpu": "500m"}}}], - "serviceAccountName": "default-editor", "volumes": [{"name": "mypvc", "persistentVolumeClaim": - {"claimName": "my-awesome-kf-workshop-1703595962"}}]}}' - - footprintai/tensorboard:2.7.0 - image: alpine - resources: - limits: {cpu: '1'} - requests: {cpu: '1'} - outputs: - artifacts: - - {name: mlpipeline-ui-metadata, path: /tmp/outputs/mlpipeline-ui-metadata/data} - metadata: - annotations: {author: Alexey Volkov , canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/tensorboard/prepare_tensorboard/component.yaml', - pipelines.kubeflow.org/component_spec: '{"description": "Pre-creates Tensorboard - visualization for a given Log dir URI.\nThis way the Tensorboard can be - viewed before the training completes.\nThe output Log dir URI should be - passed to a trainer component that will write Tensorboard logs to that directory.\n", - "implementation": {"container": {"command": ["sh", "-ex", "-c", "log_dir=\"$0\"\noutput_metadata_path=\"$1\"\npod_template_spec=\"$2\"\nimage=\"$3\"\n\nmkdir - -p \"$(dirname \"$output_metadata_path\")\"\n\necho ''\n {\n \"outputs\" - : [{\n \"type\": \"tensorboard\",\n \"source\": \"''\"$log_dir\"''\",\n \"image\": - \"''\"$image\"''\",\n \"pod_template_spec\": ''\"$pod_template_spec\"''\n }]\n }\n'' - >\"$output_metadata_path\"\n", {"inputValue": "Log dir URI"}, {"outputPath": - "mlpipeline-ui-metadata"}, {"inputValue": "Pod Template Spec"}, {"inputValue": - "Image"}], "image": "alpine"}}, "inputs": [{"name": "Log dir URI", "type": - "String"}, {"default": "", "name": "Image", "type": "String"}, {"default": - "null", "name": "Pod Template Spec", "type": "String"}], "metadata": {"annotations": - {"author": "Alexey Volkov ", "canonical_location": - "https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/tensorboard/prepare_tensorboard/component.yaml"}}, - "name": "Create Tensorboard visualization", "outputs": [{"name": "mlpipeline-ui-metadata", - "type": "kfp.v1.ui-metadata"}]}', pipelines.kubeflow.org/component_ref: '{"digest": - "cc3c37c54619129e4f57e4564bc5df0ba9719a305e6145238f2ae7e54d87f2ef", "url": - "https://raw.githubusercontent.com/kubeflow/pipelines/1b107eb4bb2510ecb99fd5f4fb438cbf7c96a87a/components/contrib/tensorflow/tensorboard/prepare_tensorboard/component.yaml"}', - pipelines.kubeflow.org/arguments.parameters: '{"Image": "footprintai/tensorboard:2.7.0", - "Log dir URI": "volume://mypvc/logs", "Pod Template Spec": "{\"spec\": {\"containers\": - [{\"volumeMounts\": [{\"mountPath\": \"/data\", \"name\": \"mypvc\"}], \"resources\": - {\"requests\": {\"cpu\": \"250m\"}, \"limits\": {\"cpu\": \"500m\"}}}], - \"serviceAccountName\": \"default-editor\", \"volumes\": [{\"name\": \"mypvc\", - \"persistentVolumeClaim\": {\"claimName\": \"my-awesome-kf-workshop-1703595962\"}}]}}"}'} - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - - name: mnist-func - container: - args: [--log-folder, /data, '----output-paths', /tmp/outputs/logdir/data] - command: - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - "def mnist_func(log_folder):\n\n print('mnist_func:', log_folder)\n \ - \ import tensorflow as tf\n import json\n mnist = tf.keras.datasets.mnist\n\ - \ (x_train,y_train), (x_test, y_test) = mnist.load_data()\n x_train,\ - \ x_test = x_train/255.0, x_test/255.0\n\n def create_model():\n \ - \ return tf.keras.models.Sequential([\n tf.keras.layers.Flatten(input_shape\ - \ = (28,28)),\n tf.keras.layers.Dense(512, activation = 'relu'),\n\ - \ tf.keras.layers.Dropout(0.2),\n tf.keras.layers.Dense(10,\ - \ activation = 'softmax')\n ])\n model = create_model()\n model.compile(optimizer='adam',\n\ - \ loss='sparse_categorical_crossentropy',\n \ - \ metrics=['accuracy'])\n import datetime\n import os\n\n ###\ - \ add tensorboard logout callback\n log_dir = os.path.join(log_folder,\ - \ \"logs\", datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n tensorboard_callback\ - \ = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n \ - \ ######\n\n model.fit(x=x_train, \n y=y_train, \n \ - \ epochs=5, \n validation_data=(x_test, y_test), \n \ - \ callbacks=[tensorboard_callback])\n\n print('At least tensorboard\ - \ callbacks are correct')\n print('logdir:', log_dir)\n return ([log_dir])\n\ - \ndef _serialize_str(str_value: str) -> str:\n if not isinstance(str_value,\ - \ str):\n raise TypeError('Value \"{}\" has type \"{}\" instead of\ - \ str.'.format(\n str(str_value), str(type(str_value))))\n return\ - \ str_value\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Mnist\ - \ func', description='')\n_parser.add_argument(\"--log-folder\", dest=\"log_folder\"\ - , type=str, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"\ - ----output-paths\", dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args\ - \ = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"_output_paths\"\ - , [])\n\n_outputs = mnist_func(**_parsed_args)\n\n_output_serializers = [\n\ - \ _serialize_str,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ - \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ - \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" - image: tensorflow/tensorflow:2.0.0-py3 - resources: - limits: {cpu: '1'} - requests: {cpu: '1'} - volumeMounts: - - {mountPath: /data, name: mypvc} - inputs: - parameters: - - {name: mypvc-name} - outputs: - artifacts: - - {name: mnist-func-logdir, path: /tmp/outputs/logdir/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--log-folder", {"inputValue": "log_folder"}, "----output-paths", - {"outputPath": "logdir"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def mnist_func(log_folder):\n\n print(''mnist_func:'', log_folder)\n import - tensorflow as tf\n import json\n mnist = tf.keras.datasets.mnist\n (x_train,y_train), - (x_test, y_test) = mnist.load_data()\n x_train, x_test = x_train/255.0, - x_test/255.0\n\n def create_model():\n return tf.keras.models.Sequential([\n tf.keras.layers.Flatten(input_shape - = (28,28)),\n tf.keras.layers.Dense(512, activation = ''relu''),\n tf.keras.layers.Dropout(0.2),\n tf.keras.layers.Dense(10, - activation = ''softmax'')\n ])\n model = create_model()\n model.compile(optimizer=''adam'',\n loss=''sparse_categorical_crossentropy'',\n metrics=[''accuracy''])\n import - datetime\n import os\n\n ### add tensorboard logout callback\n log_dir - = os.path.join(log_folder, \"logs\", datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n tensorboard_callback - = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n ######\n\n model.fit(x=x_train, - \n y=y_train, \n epochs=5, \n validation_data=(x_test, - y_test), \n callbacks=[tensorboard_callback])\n\n print(''At - least tensorboard callbacks are correct'')\n print(''logdir:'', log_dir)\n return - ([log_dir])\n\ndef _serialize_str(str_value: str) -> str:\n if not isinstance(str_value, - str):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of - str.''.format(\n str(str_value), str(type(str_value))))\n return - str_value\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Mnist - func'', description='''')\n_parser.add_argument(\"--log-folder\", dest=\"log_folder\", - type=str, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", - dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files - = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = mnist_func(**_parsed_args)\n\n_output_serializers - = [\n _serialize_str,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except - OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], - "image": "tensorflow/tensorflow:2.0.0-py3"}}, "inputs": [{"name": "log_folder", - "type": "String"}], "name": "Mnist func", "outputs": [{"name": "logdir", - "type": "String"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"log_folder": - "/data"}'} - volumes: - - name: mypvc - persistentVolumeClaim: {claimName: '{{inputs.parameters.mypvc-name}}'} - - name: mnist-pipeline - dag: - tasks: - - {name: create-tensorboard-visualization, template: create-tensorboard-visualization} - - name: mnist-func - template: mnist-func - dependencies: [create-tensorboard-visualization, mypvc] - arguments: - parameters: - - {name: mypvc-name, value: '{{tasks.mypvc.outputs.parameters.mypvc-name}}'} - - {name: mypvc, template: mypvc} - - name: mypvc - resource: - action: create - manifest: | - apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - name: '{{workflow.name}}-my-awesome-kf-workshop-1703595962' - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - outputs: - parameters: - - name: mypvc-manifest - valueFrom: {jsonPath: '{}'} - - name: mypvc-name - valueFrom: {jsonPath: '{.metadata.name}'} - - name: mypvc-size - valueFrom: {jsonPath: '{.status.capacity.storage}'} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - arguments: - parameters: [] - serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml deleted file mode 100644 index b1a4a1e25..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml +++ /dev/null @@ -1,131 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Workflow -metadata: - generateName: only-decision-tree- - annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T21:42:00.682134', - pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Decision Tree - for classification problem.", "name": "only_decision_tree"}'} - labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20} -spec: - entrypoint: only-decision-tree - templates: - - name: decision-tree-classifier - container: - args: [] - command: [python, decision_tree.py, --data, /tmp/inputs/Data/data, --accuracy, - /tmp/outputs/Accuracy/data] - image: lightnighttw/kubeflow:decision_tree_v2 - resources: - limits: - cpu: 2 - inputs: - artifacts: - - {name: download-data-function-Data, path: /tmp/inputs/Data/data} - outputs: - parameters: - - name: decision-tree-classifier-Accuracy - valueFrom: {path: /tmp/outputs/Accuracy/data} - artifacts: - - {name: decision-tree-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains - a decision tree classifier", "implementation": {"container": {"command": - ["python", "decision_tree.py", "--data", {"inputPath": "Data"}, "--accuracy", - {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:decision_tree_v2"}}, - "inputs": [{"description": "Path where data is stored.", "name": "Data", - "type": "LocalPath"}], "name": "Decision Tree classifier", "outputs": [{"description": - "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": - "c5c232a9654213b3b222693949b71a5d561d04ed09543c20b6f8f2eab651ae0b", "url": - "decision_tree/decision_tree.yaml"}'} - - name: download-data-function - container: - args: [] - command: [python, download_data.py, --data, /tmp/outputs/Data/data] - image: lightnighttw/kubeflow:download_data - resources: - limits: - cpu: 2 - outputs: - artifacts: - - {name: download-data-function-Data, path: /tmp/outputs/Data/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download - toy data from sklearn datasets", "implementation": {"container": {"command": - ["python", "download_data.py", "--data", {"outputPath": "Data"}], "image": - "lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function", - "outputs": [{"description": "Path where data will be stored.", "name": "Data", - "type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest": - "467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url": - "download_data/download_data.yaml"}'} - - name: only-decision-tree - dag: - tasks: - - name: decision-tree-classifier - template: decision-tree-classifier - dependencies: [download-data-function] - arguments: - artifacts: - - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} - - {name: download-data-function, template: download-data-function} - - name: show-results - template: show-results - dependencies: [decision-tree-classifier] - arguments: - parameters: - - {name: decision-tree-classifier-Accuracy, value: '{{tasks.decision-tree-classifier.outputs.parameters.decision-tree-classifier-Accuracy}}'} - - name: show-results - container: - args: [--decision-tree, '{{inputs.parameters.decision-tree-classifier-Accuracy}}'] - command: - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - | - def show_results(decision_tree): - # the results are shown. - - print(f"Decision tree (accuracy): {decision_tree}") - - import argparse - _parser = argparse.ArgumentParser(prog='Show results', description='') - _parser.add_argument("--decision-tree", dest="decision_tree", type=float, required=True, default=argparse.SUPPRESS) - _parsed_args = vars(_parser.parse_args()) - - _outputs = show_results(**_parsed_args) - image: python:3.7 - resources: - limits: - cpu: 2 - inputs: - parameters: - - {name: decision-tree-classifier-Accuracy} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--decision-tree", {"inputValue": "decision_tree"}], "command": - ["sh", "-ec", "program_path=$(mktemp)\nprintf \"%s\" \"$0\" > \"$program_path\"\npython3 - -u \"$program_path\" \"$@\"\n", "def show_results(decision_tree):\n # - the results are shown.\n\n print(f\"Decision tree (accuracy): {decision_tree}\")\n\nimport - argparse\n_parser = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--decision-tree\", - dest=\"decision_tree\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args - = vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"], - "image": "python:3.7"}}, "inputs": [{"name": "decision_tree", "type": "Float"}], - "name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"decision_tree": - "{{inputs.parameters.decision-tree-classifier-Accuracy}}"}'} - arguments: - parameters: [] - serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml b/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml deleted file mode 100644 index 2e10bcefa..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml +++ /dev/null @@ -1,229 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Workflow -metadata: - generateName: three-pipeline- - annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T12:05:44.365082', - pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Decision Tree, - random forest and Logistic Regression for classification problem.", "name": - "Three Pipeline"}'} - labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} -spec: - entrypoint: three-pipeline - templates: - - name: decision-tree-classifier - container: - args: [] - command: [python, decision_tree.py, --data, /tmp/inputs/Data/data, --accuracy, - /tmp/outputs/Accuracy/data] - image: lightnighttw/kubeflow:decision_tree_v2 - resources: - limits: - cpu: 2 - inputs: - artifacts: - - {name: download-data-function-Data, path: /tmp/inputs/Data/data} - outputs: - parameters: - - name: decision-tree-classifier-Accuracy - valueFrom: {path: /tmp/outputs/Accuracy/data} - artifacts: - - {name: decision-tree-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains - a decision tree classifier", "implementation": {"container": {"command": - ["python", "decision_tree.py", "--data", {"inputPath": "Data"}, "--accuracy", - {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:decision_tree_v2"}}, - "inputs": [{"description": "Path where data is stored.", "name": "Data", - "type": "LocalPath"}], "name": "Decision Tree classifier", "outputs": [{"description": - "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": - "c5c232a9654213b3b222693949b71a5d561d04ed09543c20b6f8f2eab651ae0b", "url": - "decision_tree/decision_tree.yaml"}'} - - name: download-data-function - container: - args: [] - command: [python, download_data.py, --data, /tmp/outputs/Data/data] - image: lightnighttw/kubeflow:download_data - resources: - limits: - cpu: 2 - outputs: - artifacts: - - {name: download-data-function-Data, path: /tmp/outputs/Data/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download - toy data from sklearn datasets", "implementation": {"container": {"command": - ["python", "download_data.py", "--data", {"outputPath": "Data"}], "image": - "lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function", - "outputs": [{"description": "Path where data will be stored.", "name": "Data", - "type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest": - "467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url": - "download_data/download_data.yaml"}'} - - name: logistic-regression-classifier - container: - args: [] - command: [python, logistic_regression.py, --data, /tmp/inputs/Data/data, --accuracy, - /tmp/outputs/Accuracy/data] - image: lightnighttw/kubeflow:logistic_regression - resources: - limits: - cpu: 2 - inputs: - artifacts: - - {name: download-data-function-Data, path: /tmp/inputs/Data/data} - outputs: - parameters: - - name: logistic-regression-classifier-Accuracy - valueFrom: {path: /tmp/outputs/Accuracy/data} - artifacts: - - {name: logistic-regression-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains - a Logistic Regression Classifier", "implementation": {"container": {"command": - ["python", "logistic_regression.py", "--data", {"inputPath": "Data"}, "--accuracy", - {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:logistic_regression"}}, - "inputs": [{"description": "Path where data is stored.", "name": "Data", - "type": "LocalPath"}], "name": "Logistic Regression Classifier", "outputs": - [{"description": "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', - pipelines.kubeflow.org/component_ref: '{"digest": "a8d1e77d07d18a75bef200aee96f35136833fc4bb535f33fd949a307beb094c2", - "url": "logistic_regression/logistic_regression.yaml"}'} - - name: random-forest-classifier - container: - args: [] - command: [python, randomforest.py, --data, /tmp/inputs/Data/data, --accuracy, - /tmp/outputs/Accuracy/data] - image: lightnighttw/kubeflow:random_forest_v4 - resources: - limits: - cpu: 2 - inputs: - artifacts: - - {name: download-data-function-Data, path: /tmp/inputs/Data/data} - outputs: - parameters: - - name: random-forest-classifier-Accuracy - valueFrom: {path: /tmp/outputs/Accuracy/data} - artifacts: - - {name: random-forest-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Train - a random forest classifier", "implementation": {"container": {"command": - ["python", "randomforest.py", "--data", {"inputPath": "Data"}, "--accuracy", - {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:random_forest_v4"}}, - "inputs": [{"description": "Path where data is stored.", "name": "Data", - "type": "LocalPath"}], "name": "Random Forest classifier", "outputs": [{"description": - "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": - "b49b12da3371976eddf41d662685bb49d71b419d516de65efdd90938d2c706bc", "url": - "randomForest/random_forest.yaml"}'} - - name: show-results - container: - args: [--decision-tree, '{{inputs.parameters.decision-tree-classifier-Accuracy}}', - --logistic-regression, '{{inputs.parameters.logistic-regression-classifier-Accuracy}}', - --random-forest, '{{inputs.parameters.random-forest-classifier-Accuracy}}'] - command: - - sh - - -ec - - | - program_path=$(mktemp) - printf "%s" "$0" > "$program_path" - python3 -u "$program_path" "$@" - - | - def show_results(decision_tree, logistic_regression, random_forest): - # Given the outputs from decision_tree and logistic regression components - # the results are shown. - - print(f"Decision tree (accuracy): {decision_tree}") - print(f"Logistic regression (accuracy): {logistic_regression}") - print(f"Random forest (accuracy): {random_forest}") - - import argparse - _parser = argparse.ArgumentParser(prog='Show results', description='') - _parser.add_argument("--decision-tree", dest="decision_tree", type=float, required=True, default=argparse.SUPPRESS) - _parser.add_argument("--logistic-regression", dest="logistic_regression", type=float, required=True, default=argparse.SUPPRESS) - _parser.add_argument("--random-forest", dest="random_forest", type=float, required=True, default=argparse.SUPPRESS) - _parsed_args = vars(_parser.parse_args()) - - _outputs = show_results(**_parsed_args) - image: python:3.7 - resources: - limits: - cpu: 2 - inputs: - parameters: - - {name: decision-tree-classifier-Accuracy} - - {name: logistic-regression-classifier-Accuracy} - - {name: random-forest-classifier-Accuracy} - metadata: - labels: - pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 - pipelines.kubeflow.org/pipeline-sdk-type: kfp - pipelines.kubeflow.org/enable_caching: "true" - annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": - {"args": ["--decision-tree", {"inputValue": "decision_tree"}, "--logistic-regression", - {"inputValue": "logistic_regression"}, "--random-forest", {"inputValue": - "random_forest"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf - \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", - "def show_results(decision_tree, logistic_regression, random_forest):\n # - Given the outputs from decision_tree and logistic regression components\n # - the results are shown.\n\n print(f\"Decision tree (accuracy): {decision_tree}\")\n print(f\"Logistic - regression (accuracy): {logistic_regression}\")\n print(f\"Random forest - (accuracy): {random_forest}\")\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Show - results'', description='''')\n_parser.add_argument(\"--decision-tree\", - dest=\"decision_tree\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"--logistic-regression\", - dest=\"logistic_regression\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"--random-forest\", - dest=\"random_forest\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args - = vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"], - "image": "python:3.7"}}, "inputs": [{"name": "decision_tree", "type": "Float"}, - {"name": "logistic_regression", "type": "Float"}, {"name": "random_forest", - "type": "Float"}], "name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}', - pipelines.kubeflow.org/arguments.parameters: '{"decision_tree": "{{inputs.parameters.decision-tree-classifier-Accuracy}}", - "logistic_regression": "{{inputs.parameters.logistic-regression-classifier-Accuracy}}", - "random_forest": "{{inputs.parameters.random-forest-classifier-Accuracy}}"}'} - - name: three-pipeline - dag: - tasks: - - name: decision-tree-classifier - template: decision-tree-classifier - dependencies: [download-data-function] - arguments: - artifacts: - - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} - - {name: download-data-function, template: download-data-function} - - name: logistic-regression-classifier - template: logistic-regression-classifier - dependencies: [download-data-function] - arguments: - artifacts: - - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} - - name: random-forest-classifier - template: random-forest-classifier - dependencies: [download-data-function] - arguments: - artifacts: - - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} - - name: show-results - template: show-results - dependencies: [decision-tree-classifier, logistic-regression-classifier, random-forest-classifier] - arguments: - parameters: - - {name: decision-tree-classifier-Accuracy, value: '{{tasks.decision-tree-classifier.outputs.parameters.decision-tree-classifier-Accuracy}}'} - - {name: logistic-regression-classifier-Accuracy, value: '{{tasks.logistic-regression-classifier.outputs.parameters.logistic-regression-classifier-Accuracy}}'} - - {name: random-forest-classifier-Accuracy, value: '{{tasks.random-forest-classifier.outputs.parameters.random-forest-classifier-Accuracy}}'} - arguments: - parameters: [] - serviceAccountName: pipeline-runner diff --git a/kubeflow/examples/1.connect-kubeflow/py/requirements.txt b/kubeflow/examples/1.connect-kubeflow/py/requirements.txt deleted file mode 100644 index 0a8547bcc..000000000 --- a/kubeflow/examples/1.connect-kubeflow/py/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -setuptools -wheel diff --git a/kubeflow/examples/1.connect-kubeflow/settings.js b/kubeflow/examples/1.connect-kubeflow/settings.js deleted file mode 100644 index 332013ee1..000000000 --- a/kubeflow/examples/1.connect-kubeflow/settings.js +++ /dev/null @@ -1,498 +0,0 @@ -/** - * This is the default settings file provided by Node-RED. - * - * It can contain any valid JavaScript code that will get run when Node-RED - * is started. - * - * Lines that start with // are commented out. - * Each entry should be separated from the entries above and below by a comma ',' - * - * For more information about individual settings, refer to the documentation: - * https://nodered.org/docs/user-guide/runtime/configuration - * - * The settings are split into the following sections: - * - Flow File and User Directory Settings - * - Security - * - Server Settings - * - Runtime Settings - * - Editor Settings - * - Node Settings - * - **/ - -module.exports = { - -/******************************************************************************* - * Flow File and User Directory Settings - * - flowFile - * - credentialSecret - * - flowFilePretty - * - userDir - * - nodesDir - ******************************************************************************/ - - /** The file containing the flows. If not set, defaults to flows_.json **/ - flowFile: 'flows.json', - - /** By default, credentials are encrypted in storage using a generated key. To - * specify your own secret, set the following property. - * If you want to disable encryption of credentials, set this property to false. - * Note: once you set this property, do not change it - doing so will prevent - * node-red from being able to decrypt your existing credentials and they will be - * lost. - */ - //credentialSecret: "a-secret-key", - credentialSecret: process.env.NODE_RED_CREDENTIAL_SECRET, - - /** By default, the flow JSON will be formatted over multiple lines making - * it easier to compare changes when using version control. - * To disable pretty-printing of the JSON set the following property to false. - */ - flowFilePretty: true, - - /** By default, all user data is stored in a directory called `.node-red` under - * the user's home directory. To use a different location, the following - * property can be used - */ - //userDir: '/home/nol/.node-red/', - - /** Node-RED scans the `nodes` directory in the userDir to find local node files. - * The following property can be used to specify an additional directory to scan. - */ - //nodesDir: '/home/nol/.node-red/nodes', - -/******************************************************************************* - * Security - * - adminAuth - * - https - * - httpsRefreshInterval - * - requireHttps - * - httpNodeAuth - * - httpStaticAuth - ******************************************************************************/ - - /** To password protect the Node-RED editor and admin API, the following - * property can be used. See http://nodered.org/docs/security.html for details. - */ - //adminAuth: { - // type: "credentials", - // users: [{ - // username: "admin", - // password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.", - // permissions: "*" - // }] - //}, - - /** The following property can be used to enable HTTPS - * This property can be either an object, containing both a (private) key - * and a (public) certificate, or a function that returns such an object. - * See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener - * for details of its contents. - */ - - /** Option 1: static object */ - //https: { - // key: require("fs").readFileSync('privkey.pem'), - // cert: require("fs").readFileSync('cert.pem') - //}, - - /** Option 2: function that returns the HTTP configuration object */ - // https: function() { - // // This function should return the options object, or a Promise - // // that resolves to the options object - // return { - // key: require("fs").readFileSync('privkey.pem'), - // cert: require("fs").readFileSync('cert.pem') - // } - // }, - - /** If the `https` setting is a function, the following setting can be used - * to set how often, in hours, the function will be called. That can be used - * to refresh any certificates. - */ - //httpsRefreshInterval : 12, - - /** The following property can be used to cause insecure HTTP connections to - * be redirected to HTTPS. - */ - //requireHttps: true, - - /** To password protect the node-defined HTTP endpoints (httpNodeRoot), - * including node-red-dashboard, or the static content (httpStatic), the - * following properties can be used. - * The `pass` field is a bcrypt hash of the password. - * See http://nodered.org/docs/security.html#generating-the-password-hash - */ - //httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, - //httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, - -/******************************************************************************* - * Server Settings - * - uiPort - * - uiHost - * - apiMaxLength - * - httpServerOptions - * - httpAdminRoot - * - httpAdminMiddleware - * - httpNodeRoot - * - httpNodeCors - * - httpNodeMiddleware - * - httpStatic - ******************************************************************************/ - - /** the tcp port that the Node-RED web server is listening on */ - uiPort: process.env.PORT || 1880, - - /** By default, the Node-RED UI accepts connections on all IPv4 interfaces. - * To listen on all IPv6 addresses, set uiHost to "::", - * The following property can be used to listen on a specific interface. For - * example, the following would only allow connections from the local machine. - */ - //uiHost: "127.0.0.1", - - /** The maximum size of HTTP request that will be accepted by the runtime api. - * Default: 5mb - */ - //apiMaxLength: '5mb', - - /** The following property can be used to pass custom options to the Express.js - * server used by Node-RED. For a full list of available options, refer - * to http://expressjs.com/en/api.html#app.settings.table - */ - //httpServerOptions: { }, - - /** By default, the Node-RED UI is available at http://localhost:1880/ - * The following property can be used to specify a different root path. - * If set to false, this is disabled. - */ - //httpAdminRoot: '/admin', - - /** The following property can be used to add a custom middleware function - * in front of all admin http routes. For example, to set custom http - * headers. It can be a single function or an array of middleware functions. - */ - // httpAdminMiddleware: function(req,res,next) { - // // Set the X-Frame-Options header to limit where the editor - // // can be embedded - // //res.set('X-Frame-Options', 'sameorigin'); - // next(); - // }, - - - /** Some nodes, such as HTTP In, can be used to listen for incoming http requests. - * By default, these are served relative to '/'. The following property - * can be used to specifiy a different root path. If set to false, this is - * disabled. - */ - //httpNodeRoot: '/red-nodes', - - /** The following property can be used to configure cross-origin resource sharing - * in the HTTP nodes. - * See https://github.com/troygoode/node-cors#configuration-options for - * details on its contents. The following is a basic permissive set of options: - */ - //httpNodeCors: { - // origin: "*", - // methods: "GET,PUT,POST,DELETE" - //}, - - /** If you need to set an http proxy please set an environment variable - * called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system. - * For example - http_proxy=http://myproxy.com:8080 - * (Setting it here will have no effect) - * You may also specify no_proxy (or NO_PROXY) to supply a comma separated - * list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk - */ - - /** The following property can be used to add a custom middleware function - * in front of all http in nodes. This allows custom authentication to be - * applied to all http in nodes, or any other sort of common request processing. - * It can be a single function or an array of middleware functions. - */ - //httpNodeMiddleware: function(req,res,next) { - // // Handle/reject the request, or pass it on to the http in node by calling next(); - // // Optionally skip our rawBodyParser by setting this to true; - // //req.skipRawBodyParser = true; - // next(); - //}, - - /** When httpAdminRoot is used to move the UI to a different root path, the - * following property can be used to identify a directory of static content - * that should be served at http://localhost:1880/. - */ - //httpStatic: '/home/nol/node-red-static/', - -/******************************************************************************* - * Runtime Settings - * - lang - * - logging - * - contextStorage - * - exportGlobalContextKeys - * - externalModules - ******************************************************************************/ - - /** Uncomment the following to run node-red in your preferred language. - * Available languages include: en-US (default), ja, de, zh-CN, zh-TW, ru, ko - * Some languages are more complete than others. - */ - // lang: "de", - - /** Configure the logging output */ - logging: { - /** Only console logging is currently supported */ - console: { - /** Level of logging to be recorded. Options are: - * fatal - only those errors which make the application unusable should be recorded - * error - record errors which are deemed fatal for a particular request + fatal errors - * warn - record problems which are non fatal + errors + fatal errors - * info - record information about the general running of the application + warn + error + fatal errors - * debug - record information which is more verbose than info + info + warn + error + fatal errors - * trace - record very detailed logging + debug + info + warn + error + fatal errors - * off - turn off all logging (doesn't affect metrics or audit) - */ - level: "info", - /** Whether or not to include metric events in the log output */ - metrics: false, - /** Whether or not to include audit events in the log output */ - audit: false - } - }, - - /** Context Storage - * The following property can be used to enable context storage. The configuration - * provided here will enable file-based context that flushes to disk every 30 seconds. - * Refer to the documentation for further options: https://nodered.org/docs/api/context/ - */ - //contextStorage: { - // default: { - // module:"localfilesystem" - // }, - //}, - - /** `global.keys()` returns a list of all properties set in global context. - * This allows them to be displayed in the Context Sidebar within the editor. - * In some circumstances it is not desirable to expose them to the editor. The - * following property can be used to hide any property set in `functionGlobalContext` - * from being list by `global.keys()`. - * By default, the property is set to false to avoid accidental exposure of - * their values. Setting this to true will cause the keys to be listed. - */ - exportGlobalContextKeys: false, - - /** Configure how the runtime will handle external npm modules. - * This covers: - * - whether the editor will allow new node modules to be installed - * - whether nodes, such as the Function node are allowed to have their - * own dynamically configured dependencies. - * The allow/denyList options can be used to limit what modules the runtime - * will install/load. It can use '*' as a wildcard that matches anything. - */ - externalModules: { - // autoInstall: false, /** Whether the runtime will attempt to automatically install missing modules */ - // autoInstallRetry: 30, /** Interval, in seconds, between reinstall attempts */ - // palette: { /** Configuration for the Palette Manager */ - // allowInstall: true, /** Enable the Palette Manager in the editor */ - // allowUpdate: true, /** Allow modules to be updated in the Palette Manager */ - // allowUpload: true, /** Allow module tgz files to be uploaded and installed */ - // allowList: ['*'], - // denyList: [], - // allowUpdateList: ['*'], - // denyUpdateList: [] - // }, - // modules: { /** Configuration for node-specified modules */ - // allowInstall: true, - // allowList: [], - // denyList: [] - // } - }, - - -/******************************************************************************* - * Editor Settings - * - disableEditor - * - editorTheme - ******************************************************************************/ - - /** The following property can be used to disable the editor. The admin API - * is not affected by this option. To disable both the editor and the admin - * API, use either the httpRoot or httpAdminRoot properties - */ - //disableEditor: false, - - /** Customising the editor - * See https://nodered.org/docs/user-guide/runtime/configuration#editor-themes - * for all available options. - */ - editorTheme: { - /** The following property can be used to set a custom theme for the editor. - * See https://github.com/node-red-contrib-themes/theme-collection for - * a collection of themes to chose from. - */ - //theme: "", - - /** To disable the 'Welcome to Node-RED' tour that is displayed the first - * time you access the editor for each release of Node-RED, set this to false - */ - //tours: false, - - palette: { - /** The following property can be used to order the categories in the editor - * palette. If a node's category is not in the list, the category will get - * added to the end of the palette. - * If not set, the following default order is used: - */ - //categories: ['subflows', 'common', 'function', 'network', 'sequence', 'parser', 'storage'], - }, - - projects: { - /** To enable the Projects feature, set this value to true */ - enabled: false, - workflow: { - /** Set the default projects workflow mode. - * - manual - you must manually commit changes - * - auto - changes are automatically committed - * This can be overridden per-user from the 'Git config' - * section of 'User Settings' within the editor - */ - mode: "manual" - } - }, - - codeEditor: { - /** Select the text editor component used by the editor. - * Defaults to "ace", but can be set to "ace" or "monaco" - */ - lib: "ace", - options: { - /** The follow options only apply if the editor is set to "monaco" - * - * theme - must match the file name of a theme in - * packages/node_modules/@node-red/editor-client/src/vendor/monaco/dist/theme - * e.g. "tomorrow-night", "upstream-sunburst", "github", "my-theme" - */ - theme: "vs", - /** other overrides can be set e.g. fontSize, fontFamily, fontLigatures etc. - * for the full list, see https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandaloneeditorconstructionoptions.html - */ - //fontSize: 14, - //fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace", - //fontLigatures: true, - } - } - }, - -/******************************************************************************* - * Node Settings - * - fileWorkingDirectory - * - functionGlobalContext - * - functionExternalModules - * - nodeMessageBufferMaxLength - * - ui (for use with Node-RED Dashboard) - * - debugUseColors - * - debugMaxLength - * - execMaxBufferSize - * - httpRequestTimeout - * - mqttReconnectTime - * - serialReconnectTime - * - socketReconnectTime - * - socketTimeout - * - tcpMsgQueueSize - * - inboundWebSocketTimeout - * - tlsConfigDisableLocalFiles - * - webSocketNodeVerifyClient - ******************************************************************************/ - - /** The working directory to handle relative file paths from within the File nodes - * defaults to the working directory of the Node-RED process. - */ - //fileWorkingDirectory: "", - - /** Allow the Function node to load additional npm modules directly */ - functionExternalModules: true, - - /** The following property can be used to set predefined values in Global Context. - * This allows extra node modules to be made available with in Function node. - * For example, the following: - * functionGlobalContext: { os:require('os') } - * will allow the `os` module to be accessed in a Function node using: - * global.get("os") - */ - functionGlobalContext: { - // os:require('os'), - }, - - /** The maximum number of messages nodes will buffer internally as part of their - * operation. This applies across a range of nodes that operate on message sequences. - * defaults to no limit. A value of 0 also means no limit is applied. - */ - //nodeMessageBufferMaxLength: 0, - - /** If you installed the optional node-red-dashboard you can set it's path - * relative to httpNodeRoot - * Other optional properties include - * readOnly:{boolean}, - * middleware:{function or array}, (req,res,next) - http middleware - * ioMiddleware:{function or array}, (socket,next) - socket.io middleware - */ - //ui: { path: "ui" }, - - /** Colourise the console output of the debug node */ - //debugUseColors: true, - - /** The maximum length, in characters, of any message sent to the debug sidebar tab */ - debugMaxLength: 1000, - - /** Maximum buffer size for the exec node. Defaults to 10Mb */ - //execMaxBufferSize: 10000000, - - /** Timeout in milliseconds for HTTP request connections. Defaults to 120s */ - //httpRequestTimeout: 120000, - - /** Retry time in milliseconds for MQTT connections */ - mqttReconnectTime: 15000, - - /** Retry time in milliseconds for Serial port connections */ - serialReconnectTime: 15000, - - /** Retry time in milliseconds for TCP socket connections */ - //socketReconnectTime: 10000, - - /** Timeout in milliseconds for TCP server socket connections. Defaults to no timeout */ - //socketTimeout: 120000, - - /** Maximum number of messages to wait in queue while attempting to connect to TCP socket - * defaults to 1000 - */ - //tcpMsgQueueSize: 2000, - - /** Timeout in milliseconds for inbound WebSocket connections that do not - * match any configured node. Defaults to 5000 - */ - //inboundWebSocketTimeout: 5000, - - /** To disable the option for using local files for storing keys and - * certificates in the TLS configuration node, set this to true. - */ - //tlsConfigDisableLocalFiles: true, - - /** The following property can be used to verify websocket connection attempts. - * This allows, for example, the HTTP request headers to be checked to ensure - * they include valid authentication information. - */ - //webSocketNodeVerifyClient: function(info) { - // /** 'info' has three properties: - // * - origin : the value in the Origin header - // * - req : the HTTP request - // * - secure : true if req.connection.authorized or req.connection.encrypted is set - // * - // * The function should return true if the connection should be accepted, false otherwise. - // * - // * Alternatively, if this function is defined to accept a second argument, callback, - // * it can be used to verify the client asynchronously. - // * The callback takes three arguments: - // * - result : boolean, whether to accept the connection or not - // * - code : if result is false, the HTTP error status to return - // * - reason: if result is false, the HTTP reason string to return - // */ - //}, -} diff --git a/kubeflow/examples/Dockerfile b/kubeflow/examples/Dockerfile deleted file mode 100644 index f195a77fd..000000000 --- a/kubeflow/examples/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM nodered/node-red:2.2.3-12 - -ARG PREFIX - -ENV NODE_OPTIONS=--max_old_space_size=128 - -USER root - -RUN apk update && \ - apk add py3-pip - -USER node-red -# Copy package.json to the WORKDIR so npm builds all -# of your added nodes modules for Node-RED -COPY package.json . -RUN npm install --unsafe-perm --no-update-notifier --no-fund --only=production - -ADD scripts/entrypoint.sh . - -ENTRYPOINT ["./entrypoint.sh"] diff --git a/kubeflow/examples/README.md b/kubeflow/examples/README.md deleted file mode 100644 index c56f4dd28..000000000 --- a/kubeflow/examples/README.md +++ /dev/null @@ -1,40 +0,0 @@ -#### Examples - -This example folder contains multiple node-red flow setups, each is isolated with a folder that allows you to run the different examples with the same settings. - -##### Add customized npm package - -You can add customized npm package via `npm install` or directly modify `packages.json`. Then rebuild your container image. - -##### Build - -Simply to run the following command to build node-red image - -``` -./build.sh -``` - -##### Run the container image - -To run the container image, use - -``` -KUBEFLOW_HOST= \ -KUBEFLOW_USERNAME= \ -KUBEFLOW_PASSWORD= \ -./run.sh -``` - -which would mount the current folder (i.e. ./example) onto the containers. We took this as a convenient step as you could change codes with node-red UI and the mounting volume allows the changes to be reflected onto your local file system. - -The example-args allows you to specify which example you want to run, for example - -``` -./run.sh 0.helloworld -``` - -would run the `0.helloworld` example. - -##### Visit vis UI - -then you can go to UI, check it out: http://127.0.0.1:1880/ diff --git a/kubeflow/examples/build.sh b/kubeflow/examples/build.sh deleted file mode 100644 index 37ad5136d..000000000 --- a/kubeflow/examples/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -docker compose build diff --git a/kubeflow/examples/docker-compose.yaml b/kubeflow/examples/docker-compose.yaml deleted file mode 100644 index 2a9619477..000000000 --- a/kubeflow/examples/docker-compose.yaml +++ /dev/null @@ -1,33 +0,0 @@ -################################################################################ -# Node-RED Stack or Compose -################################################################################ -# docker stack deploy node-red --compose-file docker-compose-node-red.yml -# docker-compose -f docker-compose-node-red.yml -p myNoderedProject up -################################################################################ -version: "3.7" - -services: - node-red: - image: reg.footprint-ai.com/public/kube-nodered:latest - build: - context: . - dockerfile: Dockerfile - labels: - # workaround around a docker-compose bug when image is also used by docker run (https://github.com/docker/compose/issues/10162) - com.docker.compose.container-number: "1" - environment: - - TZ=Asia/Taipei - - USERDIR=$USERDIR - - NODE_RED_CREDENTIAL_SECRET=noderedtutorial - - KUBEFLOW_HOST=$KUBEFLOW_HOST - - KUBEFLOW_USERNAME=$KUBEFLOW_USERNAME - - KUBEFLOW_PASSWORD=$KUBEFLOW_PASSWORD - ports: - - "1880:1880" - networks: - - node-red-net - volumes: - - ./:/data - -networks: - node-red-net: diff --git a/kubeflow/examples/package-lock.json b/kubeflow/examples/package-lock.json deleted file mode 100644 index a333a1615..000000000 --- a/kubeflow/examples/package-lock.json +++ /dev/null @@ -1,10782 +0,0 @@ -{ - "name": "node-red", - "version": "2.2.3", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "node-red", - "version": "2.2.3", - "license": "Apache-2.0", - "dependencies": { - "acorn": "8.7.0", - "acorn-walk": "8.2.0", - "ajv": "8.10.0", - "async-mutex": "0.3.2", - "basic-auth": "2.0.1", - "bcryptjs": "2.4.3", - "body-parser": "1.19.1", - "cheerio": "1.0.0-rc.10", - "clone": "2.1.2", - "content-type": "1.0.4", - "cookie": "0.4.2", - "cookie-parser": "1.4.6", - "cors": "2.8.5", - "cronosjs": "1.7.1", - "denque": "2.0.1", - "express": "4.17.2", - "express-session": "1.17.2", - "form-data": "4.0.0", - "fs-extra": "10.0.0", - "fs.notify": "0.0.4", - "got": "11.8.3", - "hash-sum": "2.0.0", - "hpagent": "0.1.2", - "https-proxy-agent": "5.0.0", - "i18next": "21.6.11", - "iconv-lite": "0.6.3", - "is-utf8": "0.2.1", - "js-yaml": "3.14.1", - "json-stringify-safe": "5.0.1", - "jsonata": "1.8.6", - "lodash.clonedeep": "^4.5.0", - "media-typer": "1.1.0", - "memorystore": "1.6.7", - "mime": "3.0.0", - "moment-timezone": "0.5.34", - "mqtt": "4.3.5", - "multer": "1.4.4", - "mustache": "4.2.0", - "node-red": "2.2.3", - "node-red-admin": "^2.2.3", - "node-red-contrib-pythonshell": "github:namgk/node-red-contrib-pythonshell", - "nopt": "5.0.0", - "oauth2orize": "1.11.1", - "on-headers": "1.0.2", - "passport": "0.5.2", - "passport-http-bearer": "1.0.1", - "passport-oauth2-client-password": "0.1.2", - "raw-body": "2.4.3", - "semver": "7.3.5", - "tar": "6.1.11", - "tough-cookie": "4.0.0", - "uglify-js": "3.15.1", - "uuid": "8.3.2", - "ws": "7.5.6", - "xml2js": "0.4.23" - }, - "devDependencies": { - "dompurify": "2.3.6", - "grunt": "1.5.2", - "grunt-chmod": "~1.1.1", - "grunt-cli": "~1.4.3", - "grunt-concurrent": "3.0.0", - "grunt-contrib-clean": "~2.0.0", - "grunt-contrib-compress": "2.0.0", - "grunt-contrib-concat": "~1.0.1", - "grunt-contrib-copy": "~1.0.0", - "grunt-contrib-jshint": "3.1.1", - "grunt-contrib-uglify": "5.0.1", - "grunt-contrib-watch": "~1.1.0", - "grunt-jsdoc": "2.4.1", - "grunt-jsdoc-to-markdown": "6.0.0", - "grunt-jsonlint": "2.1.3", - "grunt-mkdir": "~1.1.0", - "grunt-npm-command": "~0.1.2", - "grunt-sass": "~3.1.0", - "grunt-simple-mocha": "~0.4.1", - "grunt-simple-nyc": "^3.0.1", - "i18next-http-backend": "1.3.2", - "jquery-i18next": "1.2.1", - "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", - "marked": "4.0.12", - "minami": "1.2.3", - "mocha": "9.2.0", - "node-red-node-test-helper": "^0.2.7", - "nodemon": "2.0.15", - "proxy": "^1.0.2", - "sass": "1.49.7", - "should": "13.2.3", - "sinon": "11.1.2", - "stoppable": "^1.1.0", - "supertest": "6.2.2" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "bcrypt": "5.0.1" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.21.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@jsdoc/salty": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", - "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=v12.0.0" - } - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@node-red/editor-api": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-2.2.3.tgz", - "integrity": "sha512-lSqxKyf5FfODGCPQoJVr3m6oHxwIWhOQ6q1fIIxkL5JGQLJ3X/F5Du/hkgNUIr5W670S+WW+rYdx109ifiz1ng==", - "dependencies": { - "@node-red/editor-client": "2.2.3", - "@node-red/util": "2.2.3", - "bcryptjs": "2.4.3", - "body-parser": "1.19.1", - "clone": "2.1.2", - "cors": "2.8.5", - "express": "4.17.2", - "express-session": "1.17.2", - "memorystore": "1.6.7", - "mime": "3.0.0", - "multer": "1.4.4", - "mustache": "4.2.0", - "oauth2orize": "1.11.1", - "passport": "0.5.2", - "passport-http-bearer": "1.0.1", - "passport-oauth2-client-password": "0.1.2", - "ws": "7.5.6" - }, - "optionalDependencies": { - "bcrypt": "5.0.1" - } - }, - "node_modules/@node-red/editor-client": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-2.2.3.tgz", - "integrity": "sha512-rkxx1VDE4IRiWj9u1f3yxdrt4JUP4mBtPLaLOZfPn7gPvXPJAmzA6MTzeetLWFAopxUCuH4+xsrfl5sOh1RFwQ==" - }, - "node_modules/@node-red/nodes": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-2.2.3.tgz", - "integrity": "sha512-LRaoYQgWYGT3vDfHV+xHi33w7n9KDbNe9u77mNkLAna/PHq2IVViFWtBLm4uxhrYMYs7NNr7r+3NnVyhLGQlAQ==", - "dependencies": { - "acorn": "8.7.0", - "acorn-walk": "8.2.0", - "ajv": "8.10.0", - "body-parser": "1.19.1", - "cheerio": "1.0.0-rc.10", - "content-type": "1.0.4", - "cookie": "0.4.2", - "cookie-parser": "1.4.6", - "cors": "2.8.5", - "cronosjs": "1.7.1", - "denque": "2.0.1", - "form-data": "4.0.0", - "fs-extra": "10.0.0", - "fs.notify": "0.0.4", - "got": "11.8.3", - "hash-sum": "2.0.0", - "hpagent": "0.1.2", - "https-proxy-agent": "5.0.0", - "iconv-lite": "0.6.3", - "is-utf8": "0.2.1", - "js-yaml": "3.14.1", - "media-typer": "1.1.0", - "mqtt": "4.3.5", - "multer": "1.4.4", - "mustache": "4.2.0", - "on-headers": "1.0.2", - "raw-body": "2.4.3", - "tough-cookie": "4.0.0", - "uuid": "8.3.2", - "ws": "7.5.6", - "xml2js": "0.4.23" - } - }, - "node_modules/@node-red/registry": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-2.2.3.tgz", - "integrity": "sha512-fR//QJhqDGfq91lg9onknb13xhTXMCSTQRdR1FbvhgR5g0uS4fl7ZcKTBhWkp7OzUZ+pRInuuc6JeBZTaeLKQg==", - "dependencies": { - "@node-red/util": "2.2.3", - "clone": "2.1.2", - "fs-extra": "10.0.0", - "semver": "7.3.5", - "tar": "6.1.11", - "uglify-js": "3.15.1" - } - }, - "node_modules/@node-red/runtime": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-2.2.3.tgz", - "integrity": "sha512-NQrrhpg4daIdxkqET4n20az1sV5V5OvSpfkemKZbuXuicrPy4sGZ1OZ309v4QVbky97RgVrs7iv2Z1IRBXV8og==", - "dependencies": { - "@node-red/registry": "2.2.3", - "@node-red/util": "2.2.3", - "async-mutex": "0.3.2", - "clone": "2.1.2", - "express": "4.17.2", - "fs-extra": "10.0.0", - "json-stringify-safe": "5.0.1" - } - }, - "node_modules/@node-red/util": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@node-red/util/-/util-2.2.3.tgz", - "integrity": "sha512-N/3US+wwa3mVm3jkSV/QPfVIRdQjaXyChgRPm9UAZbls6TrxJFfZxZefQt4xNKoDYQkHoFNN65Q29RtV0GfbbA==", - "dependencies": { - "fs-extra": "10.0.0", - "i18next": "21.6.11", - "json-stringify-safe": "5.0.1", - "jsonata": "1.8.6", - "lodash.clonedeep": "^4.5.0", - "moment-timezone": "0.5.34" - } - }, - "node_modules/@prantlf/jsonlint": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@prantlf/jsonlint/-/jsonlint-10.2.0.tgz", - "integrity": "sha512-KMFfds0peWLLfCu3bhClTiEN0tdj/Z86QJvn1awKHws6r+Sx6T3a44Eadz6OvqN6ZpsRkqaRpZxqddvvDAdDZQ==", - "dev": true, - "dependencies": { - "ajv": "6.10.2", - "commander": "4.0.1" - }, - "bin": { - "jsonlint": "lib/cli.js" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@prantlf/jsonlint/node_modules/ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "node_modules/@prantlf/jsonlint/node_modules/fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", - "dev": true - }, - "node_modules/@prantlf/jsonlint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", - "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", - "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", - "dev": true - }, - "node_modules/@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", - "dev": true, - "dependencies": { - "@types/linkify-it": "*", - "@types/mdurl": "*" - } - }, - "node_modules/@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.15.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", - "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==" - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/adm-zip": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agent-base/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/agent-base/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/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escape-sequences": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", - "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", - "dev": true, - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ansi-escape-sequences/node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "node_modules/append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", - "dev": true, - "dependencies": { - "default-require-extensions": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "optional": true - }, - "node_modules/archiver": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", - "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", - "dev": true, - "dependencies": { - "archiver-utils": "^2.1.0", - "async": "^3.2.3", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.0.0", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "dev": true, - "dependencies": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/archiver/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/args": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz", - "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==", - "dev": true, - "dependencies": { - "camelcase": "5.0.0", - "chalk": "2.4.2", - "leven": "2.1.0", - "mri": "1.1.4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/args/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/args/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/args/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/args/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/args/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/args/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/args/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", - "dev": true, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/async": { - "version": "0.1.22", - "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", - "integrity": "sha512-2tEzliJmf5fHNafNwQLJXUasGzQCVctvsNkXmnlELHwypU0p08/rHohYvkqKIjyXpx+0rkrYv6QbhJ+UF4QkBg==", - "engines": { - "node": "*" - } - }, - "node_modules/async-mutex": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", - "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", - "dependencies": { - "tslib": "^2.3.1" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.0.tgz", - "integrity": "sha512-XV/WrPxXfzgZ8j4lcB5i6LyaXmi90yetmV/Fem0kmglGx+mpY06CiweL3YxU6wOTNLmqLUePW4G8h45nGZ/+pA==", - "deprecated": "Formdata complete broken, incorrect build size", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "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/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/basic-auth-parser": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/basic-auth-parser/-/basic-auth-parser-0.0.2.tgz", - "integrity": "sha512-Y7OBvWn+JnW45JWHLY6ybYub2k9cXCMrtCyO1Hds2s6eqClqWhPnOQpgXUPjAiMHj+A8TEPIQQ1dYENnJoBOHQ==", - "dev": true - }, - "node_modules/bcrypt": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", - "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^3.1.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ==", - "dev": true, - "dependencies": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - } - }, - "node_modules/body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", - "dependencies": { - "bytes": "3.1.1", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", - "type-is": "~1.6.18" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/body-parser/node_modules/raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", - "dependencies": { - "bytes": "3.1.1", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body/node_modules/bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==", - "dev": true - }, - "node_modules/body/node_modules/raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==", - "dev": true, - "dependencies": { - "bytes": "1", - "string_decoder": "0.10" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/body/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==", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", - "dependencies": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/busboy/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/busboy/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/busboy/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/bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cache-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", - "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", - "dev": true, - "dependencies": { - "array-back": "^4.0.1", - "fs-then-native": "^2.0.0", - "mkdirp2": "^1.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cache-point/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/caching-transform": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", - "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", - "dev": true, - "dependencies": { - "hasha": "^3.0.0", - "make-dir": "^2.0.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.4.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/caching-transform/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/caching-transform/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", - "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", - "dependencies": { - "css-select": "^4.3.0", - "css-what": "^6.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.3.1", - "domutils": "^2.8.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", - "dev": true, - "dependencies": { - "exit": "0.1.2", - "glob": "^7.1.1" - }, - "engines": { - "node": ">=0.2.5" - } - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", - "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", - "dependencies": { - "colors": "1.0.3" - }, - "engines": { - "node": ">= 0.2.0" - } - }, - "node_modules/cli-table/node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/collect-all": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", - "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", - "dev": true, - "dependencies": { - "stream-connect": "^1.0.2", - "stream-via": "^1.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "optional": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dev": true, - "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-args/node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/command-line-args/node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/command-line-tool": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", - "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", - "dev": true, - "dependencies": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "command-line-args": "^5.0.0", - "command-line-usage": "^4.1.0", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-tool/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/command-line-usage": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", - "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", - "dev": true, - "dependencies": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "table-layout": "^0.4.2", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/commander": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.0.1.tgz", - "integrity": "sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/commist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", - "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", - "dependencies": { - "leven": "^2.1.0", - "minimist": "^1.1.0" - } - }, - "node_modules/common-sequence": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", - "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/compress-commons": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", - "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", - "dev": true, - "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "engines": [ - "node >= 6.0" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/config-master": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", - "integrity": "sha512-n7LBL1zBzYdTpF1mx5DNcZnZn05CWIdsdvtPL4MosvqbBUK3Rq6VWEtGUuF3Y0s9/CIhMejezqlSkP6TnCJ/9g==", - "dev": true, - "dependencies": { - "walk-back": "^2.0.1" - } - }, - "node_modules/config-master/node_modules/walk-back": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", - "integrity": "sha512-Nb6GvBR8UWX1D+Le+xUq0+Q1kFmRBIWVrfLnQAOmcpEzA9oAxwJ9gIr36t9TWYfzvWRvuMtjHiVsJYEkXWaTAQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/configstore/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", - "dev": true, - "dependencies": { - "date-now": "^0.1.4" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "optional": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/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/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", - "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cookie-parser/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true - }, - "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/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cp-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", - "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "make-dir": "^2.0.0", - "nested-error-stacks": "^2.0.0", - "pify": "^4.0.1", - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cp-file/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cp-file/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/crc32-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", - "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", - "dev": true, - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cronosjs": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/cronosjs/-/cronosjs-1.7.1.tgz", - "integrity": "sha512-d6S6+ep7dJxsAG8OQQCdKuByI/S/AV64d9OF5mtmcykOyPu92cAkAnF3Tbc9s5oOaLQBYYQmTNvjqYRkPJ/u5Q==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dev": true, - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/cross-fetch/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==", - "dev": true - }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true, - "engines": { - "node": "*" - } - }, - "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/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha512-B0n2zDIXpzLzKeoEozorDSa1cHc1t0NjmxP0zuAxbizNU2MBqYJJKYXrrFdKuQliojXynrxgd7l4ahfg/+aA5g==", - "dev": true, - "dependencies": { - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "optional": true - }, - "node_modules/denque": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", - "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dev": true, - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "node_modules/dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", - "dependencies": { - "readable-stream": "1.1.x", - "streamsearch": "0.1.2" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/dicer/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/dicer/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/dicer/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/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dmd": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.2.0.tgz", - "integrity": "sha512-uXWxLF1H7TkUAuoHK59/h/ts5cKavm2LnhrIgJWisip4BVzPoXavlwyoprFFn2CzcahKYgvkfaebS6oxzgflkg==", - "dev": true, - "dependencies": { - "array-back": "^6.2.2", - "cache-point": "^2.0.0", - "common-sequence": "^2.0.2", - "file-set": "^4.0.2", - "handlebars": "^4.7.7", - "marked": "^4.2.3", - "object-get": "^2.1.1", - "reduce-flatten": "^3.0.1", - "reduce-unique": "^2.0.1", - "reduce-without": "^1.0.1", - "test-value": "^3.0.0", - "walk-back": "^5.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dmd/node_modules/marked": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", - "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/dompurify": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz", - "integrity": "sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==", - "dev": true - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", - "dev": true - }, - "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "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==", - "devOptional": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", - "dev": true, - "dependencies": { - "string-template": "~0.2.1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==", - "dev": true - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/express": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", - "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.6", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express-session": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", - "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", - "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/express-session/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express-session/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express-session/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/express/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/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/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true - }, - "node_modules/faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha512-Xhj93RXbMSq8urNCUq4p9l0P6hnySJ/7YNRhYNug0bLOuii7pKO7xQFb5mx9xZXWCar88pLPb805PvUkwrLZpQ==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/file-set": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", - "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", - "dev": true, - "dependencies": { - "array-back": "^5.0.0", - "glob": "^7.1.6" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/file-set/node_modules/array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/file-sync-cmp": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", - "integrity": "sha512-0k45oWBokCqh2MOexeYKpyqmGKG+8mQ2Wd8iawx+uWd/weWJQAZ6SoPybagdCI4xFisag8iAR77WPm4h3pTfxA==", - "dev": true - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-replace/node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha512-z8Nrwhi6wzxNMIbxlrTzuUW6KWuKkogZ/7OdDVq+0+kxn77KUH1nipx8iU6suqkHqc4y6n7a9A8IpmxY/pTjWg==", - "dev": true, - "dependencies": { - "glob": "~5.0.0" - }, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/findup-sync/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", - "dev": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", - "dev": true, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha512-3TOY+4TKV0Ml83PXJQY+JFQaHNV38lzQDIzzXYg1kWdBLenGgoZhAs0CKgzI31vi2pWEpQMq/Yi4bpKwCPkw7g==", - "dev": true, - "dependencies": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" - } - }, - "node_modules/foreground-child/node_modules/cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA==", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "node_modules/foreground-child/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formidable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.1.tgz", - "integrity": "sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==", - "dev": true, - "dependencies": { - "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", - "once": "^1.4.0", - "qs": "^6.11.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/formidable/node_modules/qs": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", - "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-then-native": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", - "integrity": "sha512-X712jAOaWXkemQCAmWeg5rOT2i+KOpWz1Z/txk/cW0qlOu2oQ9H61vc5w3X/iyuUEfq/OyaFJ78/cZAQD1/bgA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/fs.notify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fs.notify/-/fs.notify-0.0.4.tgz", - "integrity": "sha512-xnulkRf31FQwC8NsU5DEYqMTeM3jZpYsTC2hHQcHlkXTubxQHDVWkau13U/oFmFXieCkai2oKTa1MhckXk2fRQ==", - "dependencies": { - "async": "~0.1.22", - "retry": "~0.6.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "optional": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "dependencies": { - "globule": "^1.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/getobject": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz", - "integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globule": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", - "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", - "dev": true, - "dependencies": { - "glob": "~7.1.1", - "lodash": "^4.17.21", - "minimatch": "~3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/got": { - "version": "11.8.3", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", - "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/grunt": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.5.2.tgz", - "integrity": "sha512-XCtfaIu72OyDqK24MjWiGC9SwlkuhkS1mrULr1xzuJ2XqAFhP3ZAchZGHJeSCY6mkaOXU4F7SbmmCF7xIVoC9w==", - "dev": true, - "dependencies": { - "dateformat": "~3.0.3", - "eventemitter2": "~0.4.13", - "exit": "~0.1.2", - "findup-sync": "~0.3.0", - "glob": "~7.1.6", - "grunt-cli": "~1.4.3", - "grunt-known-options": "~2.0.0", - "grunt-legacy-log": "~3.0.0", - "grunt-legacy-util": "~2.0.1", - "iconv-lite": "~0.4.13", - "js-yaml": "~3.14.0", - "minimatch": "~3.0.4", - "mkdirp": "~1.0.4", - "nopt": "~3.0.6", - "rimraf": "~3.0.2" - }, - "bin": { - "grunt": "bin/grunt" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/grunt-chmod": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-chmod/-/grunt-chmod-1.1.1.tgz", - "integrity": "sha512-f807W/VOIhhaOW85JyeRd4DgB0RcbsGQV/4IvtcKctOWGvPJns4AqN7xW73PG9+RwDnSGxApS+6Xov5L2LeNXg==", - "dev": true, - "dependencies": { - "shelljs": "^0.5.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/grunt-cli": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", - "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", - "dev": true, - "dependencies": { - "grunt-known-options": "~2.0.0", - "interpret": "~1.1.0", - "liftup": "~3.0.1", - "nopt": "~4.0.1", - "v8flags": "~3.2.0" - }, - "bin": { - "grunt": "bin/grunt" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/grunt-cli/node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dev": true, - "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/grunt-concurrent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/grunt-concurrent/-/grunt-concurrent-3.0.0.tgz", - "integrity": "sha512-AgXtjUJESHEGeGX8neL3nmXBTHSj1QC48ABQ3ng2/vjuSBpDD8gKcVHSlXP71pFkIR8TQHf+eomOx6OSYSgfrA==", - "dev": true, - "dependencies": { - "arrify": "^2.0.1", - "async": "^3.1.0", - "indent-string": "^4.0.0", - "pad-stream": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "grunt": ">=1" - } - }, - "node_modules/grunt-concurrent/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/grunt-contrib-clean": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-2.0.1.tgz", - "integrity": "sha512-uRvnXfhiZt8akb/ZRDHJpQQtkkVkqc/opWO4Po/9ehC2hPxgptB9S6JHDC/Nxswo4CJSM0iFPT/Iym3cEMWzKA==", - "dev": true, - "dependencies": { - "async": "^3.2.3", - "rimraf": "^2.6.2" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "grunt": ">=0.4.5" - } - }, - "node_modules/grunt-contrib-clean/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/grunt-contrib-clean/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/grunt-contrib-compress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-2.0.0.tgz", - "integrity": "sha512-r/dAGx4qG+rmBFF4lb/hTktW2huGMGxkSLf9msh3PPtq0+cdQRQerZJ30UKevX3BLQsohwLzO0p1z/LrH6aKXQ==", - "dev": true, - "dependencies": { - "adm-zip": "^0.5.1", - "archiver": "^5.1.0", - "chalk": "^4.1.0", - "lodash": "^4.17.20", - "pretty-bytes": "^5.4.1", - "stream-buffers": "^3.0.2" - }, - "engines": { - "node": ">=10.16" - } - }, - "node_modules/grunt-contrib-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz", - "integrity": "sha512-QdTmcxe8aim2Z0dFeuSJ+f7fHIeY7PZaTMZxgvosjXwyMhpy2GUR5WHkr12lksHfZVE80v2wUwqF56wyfPUwoQ==", - "dev": true, - "dependencies": { - "chalk": "^1.0.0", - "source-map": "^0.5.3" - }, - "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "grunt": ">=0.4.0" - } - }, - "node_modules/grunt-contrib-concat/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-concat/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-concat/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-concat/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/grunt-contrib-concat/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-concat/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/grunt-contrib-copy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", - "integrity": "sha512-gFRFUB0ZbLcjKb67Magz1yOHGBkyU6uL29hiEW1tdQ9gQt72NuMKIy/kS6dsCbV0cZ0maNCb0s6y+uT1FKU7jA==", - "dev": true, - "dependencies": { - "chalk": "^1.1.1", - "file-sync-cmp": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-copy/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-copy/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-copy/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-copy/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/grunt-contrib-copy/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-copy/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/grunt-contrib-jshint": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-3.1.1.tgz", - "integrity": "sha512-EwMY6L91FqTcMlZTVoDeeq/EZL+7MoFyo1rxIea9sxyv73geVggeE37jcUhNbu5hLbxHE82CGIUqitHuR2/q+g==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "hooker": "^0.2.3", - "jshint": "~2.13.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/grunt-contrib-uglify": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-5.0.1.tgz", - "integrity": "sha512-T/aXZ4WIpAtoswZqb6HROKg7uq9QbKwl+lUuOwK4eoFj3tFv9/a/oMyd3/qvetV29Pbf8P1YYda1gDwZppr60A==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "maxmin": "^2.1.0", - "uglify-js": "^3.13.3", - "uri-path": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/grunt-contrib-uglify/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/grunt-contrib-watch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", - "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", - "dev": true, - "dependencies": { - "async": "^2.6.0", - "gaze": "^1.1.0", - "lodash": "^4.17.10", - "tiny-lr": "^1.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-contrib-watch/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/grunt-jsdoc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz", - "integrity": "sha512-S0zxU0wDewRu7z+vijEItOWe/UttxWVmvz0qz2ZVcAYR2GpXjsiski2CAVN0b18t2qeVLdmxZkJaEWCOsKzcAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1", - "jsdoc": "^3.6.3" - }, - "bin": { - "grunt-jsdoc": "bin/grunt-jsdoc" - }, - "engines": { - "node": ">= 8.12.0" - } - }, - "node_modules/grunt-jsdoc-to-markdown": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/grunt-jsdoc-to-markdown/-/grunt-jsdoc-to-markdown-6.0.0.tgz", - "integrity": "sha512-vvanKUErp6CHl4MuLQ9vwJewpMu8Fi7z09lr4OwMLr+GBu3nG5lRNZuu5mkWY8qv1aU8WkX97/rJaVs3A1Wx8g==", - "dev": true, - "dependencies": { - "jsdoc-to-markdown": "^7.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "grunt": ">=1.3.0" - } - }, - "node_modules/grunt-jsonlint": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/grunt-jsonlint/-/grunt-jsonlint-2.1.3.tgz", - "integrity": "sha512-h04qC969LIyhsJaASeJ/hDnnKnsnSNZKqjYHra6cc/WQzrfMZinQPdr11FhU4T8OzAq6ecMX5QauYiJkbjUV/Q==", - "dev": true, - "dependencies": { - "@prantlf/jsonlint": "10.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/grunt-known-options": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", - "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt-legacy-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", - "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", - "dev": true, - "dependencies": { - "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.1.0", - "hooker": "~0.2.3", - "lodash": "~4.17.19" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/grunt-legacy-log-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", - "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", - "dev": true, - "dependencies": { - "chalk": "~4.1.0", - "lodash": "~4.17.19" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/grunt-legacy-util": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", - "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", - "dev": true, - "dependencies": { - "async": "~3.2.0", - "exit": "~0.1.2", - "getobject": "~1.0.0", - "hooker": "~0.2.3", - "lodash": "~4.17.21", - "underscore.string": "~3.3.5", - "which": "~2.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/grunt-legacy-util/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/grunt-mkdir": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-mkdir/-/grunt-mkdir-1.1.0.tgz", - "integrity": "sha512-FRE17OYVveNbVJFX8GPGa5bzH2ZiAdBx3q0Kwk2Dg6l+TzLGaTdufUxiUWUbS2MERFacnmXZwDDOR5ZbYW0o+Q==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - }, - "peerDependencies": { - "grunt": ">=0.4.0" - } - }, - "node_modules/grunt-npm-command": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/grunt-npm-command/-/grunt-npm-command-0.1.2.tgz", - "integrity": "sha512-QsGLL8Pp+tzeIkCqohIbOtVopOhINErRVpxKY+SnvSEE3BXOKKSanlIh9cd1mliajO57sXG2ZC4R8L3v2NSPTQ==", - "dev": true, - "peerDependencies": { - "grunt": ">=0.4.0" - } - }, - "node_modules/grunt-sass": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.1.0.tgz", - "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", - "dev": true, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "grunt": ">=1" - } - }, - "node_modules/grunt-simple-mocha": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/grunt-simple-mocha/-/grunt-simple-mocha-0.4.1.tgz", - "integrity": "sha512-EibTuZVvyLd9v/9An+5sL+XLoArs1QkFSTUcOG/AbBzeCYemZppcO9YSEspWUwU/T/NNtAyzB+x7B6zAmKQqkA==", - "dev": true, - "dependencies": { - "mocha": "*" - }, - "bin": { - "grunt-simple-mocha": "bin/grunt-simple-mocha" - }, - "engines": { - "node": "*" - } - }, - "node_modules/grunt-simple-nyc": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/grunt-simple-nyc/-/grunt-simple-nyc-3.0.1.tgz", - "integrity": "sha512-/YLY+jNI6gBuVO3xu07zwvDN+orTAFS50W00yb/2ncvc2PFO4pR+oU7TyiHhe8a6O3KuQDHsyCE0iE+rqJagQg==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15", - "nyc": "^14.1.0", - "simple-cli": "^5.0.3" - } - }, - "node_modules/grunt/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/grunt/node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/gzip-size": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", - "integrity": "sha512-6s8trQiK+OMzSaCSVXX+iqIcLV9tC+E73jrJrJTyS4h/AJhlxHvzFKqM1YLDJWRGgHX8uLkBeXkA0njNj39L4w==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.1" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "optional": true - }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" - }, - "node_modules/hasha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", - "integrity": "sha512-w0Kz8lJFBoyaurBiNrIvxPqr/gJ6fOfSkpAPOepN3oECqGJag37xPbOv57izi/KP8auHgNYxn5fXtAb+1LsJ6w==", - "dev": true, - "dependencies": { - "is-stream": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/help-me": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", - "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", - "dependencies": { - "glob": "^7.1.6", - "readable-stream": "^3.6.0" - } - }, - "node_modules/hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hooker": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", - "integrity": "sha512-t+UerCsQviSymAInD01Pw+Dn/usmz1sRO+3Zk1+lx8eg+WKpD2ulcwWqHHL0+aseRBr+3+vIhiG1K1JTwaIcTA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/hpagent": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-0.1.2.tgz", - "integrity": "sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent/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/https-proxy-agent/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/i18next": { - "version": "21.6.11", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.11.tgz", - "integrity": "sha512-tJ2+o0lVO+fhi8bPkCpBAeY1SgkqmQm5NzgPWCQssBrywJw98/o+Kombhty5nxQOpHtvMmsxcOopczUiH6bJxQ==", - "funding": [ - { - "type": "individual", - "url": "https://locize.com" - }, - { - "type": "individual", - "url": "https://locize.com/i18next.html" - }, - { - "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" - } - ], - "dependencies": { - "@babel/runtime": "^7.12.0" - } - }, - "node_modules/i18next-http-backend": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.3.2.tgz", - "integrity": "sha512-SfcoUmsSWnc2LYsDsCq5TCg18cxJXvXymX9N37V+qqMKQY8Gf0rWkjOnRd20sMK633Dq4NF9tvqPbOiFJ49Kbw==", - "dev": true, - "dependencies": { - "cross-fetch": "3.1.5" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "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/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "node_modules/immutable": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", - "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", - "dev": true - }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha512-CLM8SNMDu7C5psFCn6Wg/tgpj/bKAg7hc2gWqcuR9OD5Ft9PhBpIu8PLicPeis+xDd6YX2ncI8MCA64I9tftIA==", - "dev": true - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, - "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/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-hook": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", - "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", - "dev": true, - "dependencies": { - "append-transform": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, - "dependencies": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/istanbul-lib-source-maps/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", - "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jquery-i18next": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jquery-i18next/-/jquery-i18next-1.2.1.tgz", - "integrity": "sha512-UNcw3rgxoKjGEg4w23FEn2h3OlPJU7rPzsgDuXDBZktIzeiVbJohs9Cv9hj8oP8KNfBRKOoErL/OVxg2FaAR4g==", - "dev": true - }, - "node_modules/js-sdsl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", - "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "dependencies": { - "xmlcreate": "^2.0.4" - } - }, - "node_modules/jsdoc": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", - "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.9.4", - "@types/markdown-it": "^12.2.3", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^3.0.0", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.13.2" - }, - "bin": { - "jsdoc": "jsdoc.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsdoc-api": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.2.0.tgz", - "integrity": "sha512-93YDnlm/OYTlLOFeNs4qAv0RBCJ0kGj67xQaWy8wrbk97Rw1EySitoOTHsTHXPEs3uyx2IStPKGrbE7LTnZXbA==", - "dev": true, - "dependencies": { - "array-back": "^6.2.2", - "cache-point": "^2.0.0", - "collect-all": "^1.0.4", - "file-set": "^4.0.2", - "fs-then-native": "^2.0.0", - "jsdoc": "^4.0.0", - "object-to-spawn-args": "^2.0.1", - "temp-path": "^1.0.0", - "walk-back": "^5.1.0" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/jsdoc-api/node_modules/jsdoc": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", - "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.15", - "@jsdoc/salty": "^0.2.1", - "@types/markdown-it": "^12.2.3", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^3.0.0", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "underscore": "~1.13.2" - }, - "bin": { - "jsdoc": "jsdoc.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsdoc-nr-template": { - "version": "1.0.0", - "resolved": "git+ssh://git@github.com/node-red/jsdoc-nr-template.git#3c7c8f96d585c7c5918a2e63519310e1297e162d", - "dev": true - }, - "node_modules/jsdoc-parse": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.2.0.tgz", - "integrity": "sha512-Afu1fQBEb7QHt6QWX/6eUWvYHJofB90Fjx7FuJYF7mnG9z5BkAIpms1wsnvYLytfmqpEENHs/fax9p8gvMj7dw==", - "dev": true, - "dependencies": { - "array-back": "^6.2.2", - "lodash.omit": "^4.5.0", - "lodash.pick": "^4.4.0", - "reduce-extract": "^1.0.0", - "sort-array": "^4.1.5", - "test-value": "^3.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdoc-to-markdown": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", - "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", - "dev": true, - "dependencies": { - "array-back": "^6.2.2", - "command-line-tool": "^0.8.0", - "config-master": "^3.1.0", - "dmd": "^6.1.0", - "jsdoc-api": "^7.1.1", - "jsdoc-parse": "^6.1.0", - "walk-back": "^5.1.0" - }, - "bin": { - "jsdoc2md": "bin/cli.js" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jshint": { - "version": "2.13.6", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.6.tgz", - "integrity": "sha512-IVdB4G0NTTeQZrBoM8C5JFVLjV2KtZ9APgybDA1MK73xb09qFs0jCXyQLnCOp1cSZZZbvhq/6mfXHUTaDkffuQ==", - "dev": true, - "dependencies": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.21", - "minimatch": "~3.0.2", - "strip-json-comments": "1.0.x" - }, - "bin": { - "jshint": "bin/jshint" - } - }, - "node_modules/jshint/node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "node_modules/jshint/node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/jshint/node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/jshint/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true - }, - "node_modules/jshint/node_modules/domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", - "dev": true, - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/jshint/node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", - "dev": true, - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/jshint/node_modules/entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==", - "dev": true - }, - "node_modules/jshint/node_modules/htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", - "dev": true, - "dependencies": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "node_modules/jshint/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==", - "dev": true - }, - "node_modules/jshint/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==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/jshint/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==", - "dev": true - }, - "node_modules/jshint/node_modules/strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", - "dev": true, - "bin": { - "strip-json-comments": "cli.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "node_modules/jsonata": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-1.8.6.tgz", - "integrity": "sha512-ZH2TPYdNP2JecOl/HvrH47Xc+9imibEMQ4YqKy/F/FrM+2a6vfbGxeCX23dB9Fr6uvGwv+ghf1KxWB3iZk09wA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "node_modules/key-list": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/key-list/-/key-list-0.1.4.tgz", - "integrity": "sha512-DMGLZAmEoKRUHPlc772EW0i92P/WY12/oWYc2pQZb5MVGOSjYmF0BEQXbOLjbou1+/PqZ+CivwfyjaUwmyl4CQ==", - "dev": true - }, - "node_modules/keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.9" - } - }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/liftup": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", - "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", - "dev": true, - "dependencies": { - "extend": "^3.0.2", - "findup-sync": "^4.0.0", - "fined": "^1.2.0", - "flagged-respawn": "^1.0.1", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.1", - "rechoir": "^0.7.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/liftup/node_modules/findup-sync": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", - "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^4.0.2", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/livereload-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", - "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", - "dev": true - }, - "node_modules/lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==", - "dev": true - }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", - "dev": true - }, - "node_modules/lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "devOptional": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "devOptional": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it-anchor": { - "version": "8.6.7", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", - "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", - "dev": true, - "peerDependencies": { - "@types/markdown-it": "*", - "markdown-it": "*" - } - }, - "node_modules/markdown-it/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/marked": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", - "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/maxmin": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", - "integrity": "sha512-NWlApBjW9az9qRPaeg7CX4sQBWwytqz32bIEo1PW9pRW+kBP9KLRfJO3UC+TV31EcQZEUq7eMzikC7zt3zPJcw==", - "dev": true, - "dependencies": { - "chalk": "^1.0.0", - "figures": "^1.0.1", - "gzip-size": "^3.0.0", - "pretty-bytes": "^3.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/maxmin/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maxmin/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maxmin/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maxmin/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/maxmin/node_modules/pretty-bytes": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", - "integrity": "sha512-eb7ZAeUTgfh294cElcu51w+OTRp/6ItW758LjwJSK72LDevcuJn0P4eD71PLMDGPwwatXmAmYHTkzvpKlJE3ow==", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maxmin/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maxmin/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/memorystore": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/memorystore/-/memorystore-1.6.7.tgz", - "integrity": "sha512-OZnmNY/NDrKohPQ+hxp0muBcBKrzKNtHr55DbqSx9hLsYVNnomSAMRAtI7R64t3gf3ID7tHQA7mG4oL3Hu9hdw==", - "dependencies": { - "debug": "^4.3.0", - "lru-cache": "^4.0.3" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/memorystore/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/memorystore/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/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/merge-source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/minami": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/minami/-/minami-1.2.3.tgz", - "integrity": "sha512-3f2QqqbUC1usVux0FkQMFYB73yd9JIxmHSn1dWQacizL6hOUaNu6mA3KxZ9SfiCc4qgcgq+5XP59+hP7URa1Dw==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp2": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", - "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", - "dev": true - }, - "node_modules/mocha": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.0.tgz", - "integrity": "sha512-kNn7E8g2SzVcq0a77dkphPsDSN7P+iYkqE0ZsGCYWRsoiKjOt+NvXfaagik8vuDa6W5Zw3qxe8Jfpt5qKf+6/Q==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.2.0", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.34", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", - "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", - "dependencies": { - "moment": ">= 2.9.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mqtt": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.5.tgz", - "integrity": "sha512-l29WGHAc0EayK1cjb6moozc+rlgK6YRCPbP3zB1CrJw84Bjk4kG9EJCXojdn4r29lA80SCqxRKq1QJ87+Xevng==", - "dependencies": { - "commist": "^1.0.0", - "concat-stream": "^2.0.0", - "debug": "^4.1.1", - "duplexify": "^4.1.1", - "help-me": "^3.0.0", - "inherits": "^2.0.3", - "lru-cache": "^6.0.0", - "minimist": "^1.2.5", - "mqtt-packet": "^6.8.0", - "number-allocator": "^1.0.9", - "pump": "^3.0.0", - "readable-stream": "^3.6.0", - "reinterval": "^1.1.0", - "rfdc": "^1.3.0", - "split2": "^3.1.0", - "ws": "^7.5.5", - "xtend": "^4.0.2" - }, - "bin": { - "mqtt": "bin/mqtt.js", - "mqtt_pub": "bin/pub.js", - "mqtt_sub": "bin/sub.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mqtt-packet": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", - "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", - "dependencies": { - "bl": "^4.0.2", - "debug": "^4.1.1", - "process-nextick-args": "^2.0.1" - } - }, - "node_modules/mqtt-packet/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/mqtt-packet/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/mqtt/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/mqtt/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mqtt/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/mqtt/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/mri": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", - "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/multer": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", - "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", - "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^0.2.11", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "on-finished": "^2.3.0", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/multer/node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/multer/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/multer/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/multer/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "node_modules/nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/nested-error-stacks": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", - "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==", - "dev": true - }, - "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0" - } - }, - "node_modules/nise/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==", - "dev": true - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "optional": true - }, - "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "optional": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-red": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/node-red/-/node-red-2.2.3.tgz", - "integrity": "sha512-sfOsWONOF5TyNApXv6AkLzwfxq+C+3lyUrXRvyuQxWt1dSGvfg417dbEx4WW0kxwREGZ47TKtLejnoTPnV5adQ==", - "dependencies": { - "@node-red/editor-api": "2.2.3", - "@node-red/nodes": "2.2.3", - "@node-red/runtime": "2.2.3", - "@node-red/util": "2.2.3", - "basic-auth": "2.0.1", - "bcryptjs": "2.4.3", - "express": "4.17.2", - "fs-extra": "10.0.0", - "node-red-admin": "^2.2.3", - "nopt": "5.0.0", - "semver": "7.3.5" - }, - "bin": { - "node-red": "red.js", - "node-red-pi": "bin/node-red-pi" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "bcrypt": "5.0.1" - } - }, - "node_modules/node-red-admin": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/node-red-admin/-/node-red-admin-2.2.4.tgz", - "integrity": "sha512-DlJpMFopqBNj10k5rGGI9ZNBi+whAIS+IHrSZH1xllfuJKZxQBZgR+o+rJeufDyc0OBRgHRqmX776HrBrlDtMA==", - "dependencies": { - "ansi-colors": "^4.1.1", - "axios": "0.27.0", - "bcryptjs": "^2.4.3", - "cli-table": "^0.3.11", - "enquirer": "^2.3.6", - "minimist": "^1.2.6", - "mustache": "^4.2.0", - "read": "^1.0.7" - }, - "bin": { - "node-red-admin": "node-red-admin.js" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "bcrypt": "5.0.1" - } - }, - "node_modules/node-red-contrib-pythonshell": { - "version": "1.5.4", - "resolved": "git+ssh://git@github.com/namgk/node-red-contrib-pythonshell.git#6bcc7df0003600bde8d688ece9c8d20caa00992f", - "license": "ISC" - }, - "node_modules/node-red-node-test-helper": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/node-red-node-test-helper/-/node-red-node-test-helper-0.2.7.tgz", - "integrity": "sha512-OanSQ1hrsigHVtMjL/cuhtjxhTdRBXxd3IALJC9eg0WOHRF75ZI7RYhFWqqOsvQ++BwmNj8ki1S49D8cZyZTWA==", - "dev": true, - "dependencies": { - "body-parser": "1.19.0", - "express": "4.17.1", - "read-pkg-up": "7.0.1", - "semver": "7.3.4", - "should": "^13.2.3", - "should-sinon": "0.0.6", - "sinon": "9.2.4", - "stoppable": "1.1.0", - "supertest": "4.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-red-node-test-helper/node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/node-red-node-test-helper/node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/node-red-node-test-helper/node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/node-red-node-test-helper/node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-red-node-test-helper/node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-red-node-test-helper/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/node-red-node-test-helper/node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/node-red-node-test-helper/node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "dev": true, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/node-red-node-test-helper/node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-red-node-test-helper/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/node-red-node-test-helper/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-red-node-test-helper/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/node-red-node-test-helper/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/node-red-node-test-helper/node_modules/nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/nise/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==", - "dev": true - }, - "node_modules/node-red-node-test-helper/node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/node-red-node-test-helper/node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/node-red-node-test-helper/node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/node-red-node-test-helper/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/node-red-node-test-helper/node_modules/semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-red-node-test-helper/node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "node_modules/node-red-node-test-helper/node_modules/sinon": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", - "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/node-red-node-test-helper/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", - "dev": true, - "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/superagent/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/node-red-node-test-helper/node_modules/supertest": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", - "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/node-red-node-test-helper/node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/node-red-node-test-helper/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/nodemon": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", - "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^3.2.7", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.8", - "semver": "^5.7.1", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5", - "update-notifier": "^5.1.0" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/nodemon/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-allocator": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", - "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", - "dependencies": { - "debug": "^4.3.1", - "js-sdsl": "4.3.0" - } - }, - "node_modules/number-allocator/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/number-allocator/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/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nyc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", - "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", - "dev": true, - "dependencies": { - "archy": "^1.0.0", - "caching-transform": "^3.0.2", - "convert-source-map": "^1.6.0", - "cp-file": "^6.2.0", - "find-cache-dir": "^2.1.0", - "find-up": "^3.0.0", - "foreground-child": "^1.5.6", - "glob": "^7.1.3", - "istanbul-lib-coverage": "^2.0.5", - "istanbul-lib-hook": "^2.0.7", - "istanbul-lib-instrument": "^3.3.0", - "istanbul-lib-report": "^2.0.8", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^2.2.4", - "js-yaml": "^3.13.1", - "make-dir": "^2.1.0", - "merge-source-map": "^1.1.0", - "resolve-from": "^4.0.0", - "rimraf": "^2.6.3", - "signal-exit": "^3.0.2", - "spawn-wrap": "^1.4.2", - "test-exclude": "^5.2.3", - "uuid": "^3.3.2", - "yargs": "^13.2.2", - "yargs-parser": "^13.0.0" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nyc/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/nyc/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/nyc/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/nyc/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nyc/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/nyc/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nyc/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nyc/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nyc/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/nyc/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/nyc/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/nyc/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/oauth2orize": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/oauth2orize/-/oauth2orize-1.11.1.tgz", - "integrity": "sha512-9dSx/Gwm0J2Rvj4RH9+h7iXVnRXZ6biwWRgb2dCeQhCosODS0nYdM9I/G7BUGsjbgn0pHjGcn1zcCRtzj2SlRA==", - "dependencies": { - "debug": "2.x.x", - "uid2": "0.0.x", - "utils-merge": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-get": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", - "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", - "dev": true - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-to-spawn-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", - "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", - "dev": true, - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", - "dev": true, - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/opted": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/opted/-/opted-1.0.2.tgz", - "integrity": "sha512-uEvunmdmKcSFiBSmnY2E9E/HbghO5yc1J0yNmq7T18YkAJeWNlo33e6VYKkRK4eudVrpvvlLdemAeAuL6rZxjQ==", - "dev": true, - "dependencies": { - "lodash": "^4.17.4" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", - "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json/node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json/node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json/node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/package-json/node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "node_modules/package-json/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/package-json/node_modules/got/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json/node_modules/got/node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/package-json/node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", - "dev": true - }, - "node_modules/package-json/node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/package-json/node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json/node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json/node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", - "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/package-json/node_modules/responselike/node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/pad-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pad-stream/-/pad-stream-2.0.0.tgz", - "integrity": "sha512-3QeQw19K48BQzUGZ9dEf/slX5Jbfy5ZeBTma2XICketO7kFNK7omF00riVcecOKN+DSiJZcK2em1eYKaVOeXKg==", - "dev": true, - "dependencies": { - "pumpify": "^1.3.3", - "split2": "^2.1.1", - "through2": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pad-stream/node_modules/split2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", - "dev": true, - "dependencies": { - "through2": "^2.0.2" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.2.tgz", - "integrity": "sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw==", - "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/passport-http-bearer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", - "integrity": "sha512-SELQM+dOTuMigr9yu8Wo4Fm3ciFfkMq5h/ZQ8ffi4ELgZrX1xh9PlglqZdcUZ1upzJD/whVyt+YWF62s3U6Ipw==", - "dependencies": { - "passport-strategy": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-oauth2-client-password": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/passport-oauth2-client-password/-/passport-oauth2-client-password-0.1.2.tgz", - "integrity": "sha512-GHQH4UtaEZvCLulAxGKHYoSsPRoPRmGsdmaZtMh5nmz80yMLQbdMA9Bg2sp4/UW3PIxJH/143hVjPTiXaNngTQ==", - "dependencies": { - "passport-strategy": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/proxy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/proxy/-/proxy-1.0.2.tgz", - "integrity": "sha512-KNac2ueWRpjbUh77OAFPZuNdfEqNynm9DD4xHT14CccGpW8wKZwEkN0yjlb7X9G9Z9F55N0Q+1z+WfgAhwYdzQ==", - "dev": true, - "dependencies": { - "args": "5.0.1", - "basic-auth-parser": "0.0.2", - "debug": "^4.1.1" - }, - "bin": { - "proxy": "bin/proxy.js" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/proxy/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/pumpify/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "dependencies": { - "escape-goat": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdir-glob": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz", - "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", - "dev": true, - "dependencies": { - "minimatch": "^5.1.0" - } - }, - "node_modules/readdir-glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", - "dev": true, - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/reduce-extract": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", - "integrity": "sha512-QF8vjWx3wnRSL5uFMyCjDeDc5EBMiryoT9tz94VvgjKfzecHAVnqmXAwQDcr7X4JmLc2cjkjFGCVzhMqDjgR9g==", - "dev": true, - "dependencies": { - "test-value": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-extract/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/reduce-extract/node_modules/test-value": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", - "integrity": "sha512-wrsbRo7qP+2Je8x8DsK8ovCGyxe3sYfQwOraIY/09A2gFXU9DYKiTF14W4ki/01AEh56kMzAmlj9CaHGDDUBJA==", - "dev": true, - "dependencies": { - "array-back": "^1.0.2", - "typical": "^2.4.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-flatten": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", - "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/reduce-unique": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", - "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/reduce-without": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", - "integrity": "sha512-zQv5y/cf85sxvdrKPlfcRzlDn/OqKFThNimYmsS3flmkioKvkUGn2Qg9cJVoQiEvdxFGLE0MQER/9fZ9sUqdxg==", - "dev": true, - "dependencies": { - "test-value": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-without/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/reduce-without/node_modules/test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w==", - "dev": true, - "dependencies": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", - "dev": true, - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reinterval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", - "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==" - }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", - "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/requizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", - "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21" - } - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.6.1.tgz", - "integrity": "sha512-txv1qsctZq8ei9J/uCXgaKKFPjlBB0H2hvtnzw9rjKWFNUFtKh59WprXxpAeAey3/QeWwHdxMFqStPaOAgy+dA==", - "engines": { - "node": "*" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "devOptional": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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/safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha512-o0JmTu17WGUaUOHa1l0FPGXKBfijbxK6qoHzlkihsDXxzBHvJcA7zgviKR92Xs841rX9pK16unfphLq0/KqX7A==", - "dev": true - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sass": { - "version": "1.49.7", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.7.tgz", - "integrity": "sha512-13dml55EMIR2rS4d/RDHHP0sXMY3+30e1TKsyXaSz3iLWVoDWEoboY8WzJd5JMnxrRHffKO3wq2mpJ0jxRJiEQ==", - "dev": true, - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "devOptional": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shelljs": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", - "integrity": "sha512-C2FisSSW8S6TIYHHiMHN0NqzdjWfTekdMpA2FJTbRWnQMLO1RRIXEB9eVZYOlofYmjZA7fY3ChoFu09MeI3wlQ==", - "dev": true, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/should": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", - "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", - "dev": true, - "dependencies": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" - } - }, - "node_modules/should-equal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", - "dev": true, - "dependencies": { - "should-type": "^1.4.0" - } - }, - "node_modules/should-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", - "dev": true, - "dependencies": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" - } - }, - "node_modules/should-sinon": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/should-sinon/-/should-sinon-0.0.6.tgz", - "integrity": "sha512-ScBOH5uW5QVFaONmUnIXANSR6z5B8IKzEmBP3HE5sPOCDuZ88oTMdUdnKoCVQdLcCIrRrhRLPS5YT+7H40a04g==", - "dev": true, - "peerDependencies": { - "should": ">= 8.x" - } - }, - "node_modules/should-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", - "dev": true - }, - "node_modules/should-type-adaptors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", - "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", - "dev": true, - "dependencies": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" - } - }, - "node_modules/should-util": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", - "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "devOptional": true - }, - "node_modules/simple-cli": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/simple-cli/-/simple-cli-5.0.5.tgz", - "integrity": "sha512-Er2FhsIayL/sktxg6fOCdNQJBTXhlf/fswNFsdmks88xsHzQ/IXGwxYgSSKeXBq4yqn83/iD4Sg8yjagwysUgw==", - "dev": true, - "dependencies": { - "async": "^3.1.0", - "chalk": "^2.4.2", - "cross-spawn": "^7.0.0", - "key-list": "^0.1.4", - "lodash": "^4.17.15", - "opted": "^1.0.0" - } - }, - "node_modules/simple-cli/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/simple-cli/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/simple-cli/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/simple-cli/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/simple-cli/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/simple-cli/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/simple-cli/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/simple-cli/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/sinon": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", - "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^7.1.2", - "@sinonjs/samsam": "^6.0.2", - "diff": "^5.0.0", - "nise": "^5.1.0", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sort-array": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.5.tgz", - "integrity": "sha512-Ya4peoS1fgFN42RN1REk2FgdNOeLIEMKFGJvs7VTP3OklF8+kl2SkpVliZ4tk/PurWsrWRsdNdU+tgyOBkB9sA==", - "dev": true, - "dependencies": { - "array-back": "^5.0.0", - "typical": "^6.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sort-array/node_modules/array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/sort-array/node_modules/typical": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", - "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spawn-wrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", - "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", - "dev": true, - "dependencies": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", - "signal-exit": "^3.0.2", - "which": "^1.3.0" - } - }, - "node_modules/spawn-wrap/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/spawn-wrap/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/spawn-wrap/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "dev": true, - "engines": { - "node": ">=4", - "npm": ">=6" - } - }, - "node_modules/stream-buffers": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", - "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/stream-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", - "integrity": "sha512-68Kl+79cE0RGKemKkhxTSg8+6AGrqBt+cbZAXevg2iJ6Y3zX4JhA/sZeGzLpxW9cXhmqAcE7KnJCisUmIUfnFQ==", - "dev": true, - "dependencies": { - "array-back": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-connect/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, - "node_modules/stream-via": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", - "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/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/string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==", - "dev": true - }, - "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==", - "devOptional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", - "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", - "dev": true, - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "^2.5.0", - "qs": "^6.10.3", - "readable-stream": "^3.6.0", - "semver": "^7.3.7" - }, - "engines": { - "node": ">=6.4.0 <13 || >=14" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/superagent/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/superagent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/superagent/node_modules/qs": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", - "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/superagent/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/superagent/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/supertest": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.2.2.tgz", - "integrity": "sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^7.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/table-layout": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", - "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", - "dev": true, - "dependencies": { - "array-back": "^2.0.0", - "deep-extend": "~0.6.0", - "lodash.padend": "^4.6.1", - "typical": "^2.6.1", - "wordwrapjs": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", - "dev": true - }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/temp-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", - "integrity": "sha512-TvmyH7kC6ZVTYkqCODjJIbgvu0FKiwQpZ4D1aknE7xpcDf/qEOB8KZEK5ef2pfbVoiBhNWs3yx4y+ESMtNYmlg==", - "dev": true - }, - "node_modules/test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", - "dev": true, - "dependencies": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/test-exclude/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/test-exclude/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/test-exclude/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/test-exclude/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/test-exclude/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/test-exclude/node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", - "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/test-exclude/node_modules/read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/test-value": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", - "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", - "dev": true, - "dependencies": { - "array-back": "^2.0.0", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/test-value/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/tiny-lr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", - "dev": true, - "dependencies": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" - } - }, - "node_modules/tiny-lr/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/tiny-lr/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/touch/node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/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/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "devOptional": true - }, - "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg==", - "dev": true - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/uglify-js": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz", - "integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==", - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "dev": true - }, - "node_modules/underscore.string": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", - "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", - "dev": true, - "dependencies": { - "sprintf-js": "^1.1.1", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/underscore.string/node_modules/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "dependencies": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uri-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", - "integrity": "sha512-8pMuAn4KacYdGMkFaoQARicp4HSw24/DHOVKWqVRJ8LhhAwPPFpdGvdL9184JVmUwe7vz7Z9n6IqI6t5n2ELdg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/walk-back": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", - "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", - "dev": true, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "devOptional": true - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "devOptional": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", - "dev": true - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "optional": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "node_modules/wordwrapjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", - "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", - "dev": true, - "dependencies": { - "reduce-flatten": "^1.0.1", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/wordwrapjs/node_modules/reduce-flatten": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", - "integrity": "sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "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" - } - }, - "node_modules/xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zip-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", - "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", - "dev": true, - "dependencies": { - "archiver-utils": "^2.1.0", - "compress-commons": "^4.1.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - } - } -} diff --git a/kubeflow/examples/package.json b/kubeflow/examples/package.json deleted file mode 100644 index bd277eebc..000000000 --- a/kubeflow/examples/package.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "name": "node-red", - "version": "2.2.3", - "description": "Low-code programming for event-driven applications", - "homepage": "http://nodered.org", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/node-red/node-red.git" - }, - "private": "true", - "scripts": { - "start": "node $NODE_OPTIONS node_modules/node-red/red.js", - "test": "grunt", - "build": "grunt build", - "dev": "grunt dev", - "build-dev": "grunt build-dev", - "docs": "grunt docs" - }, - "contributors": [ - { - "name": "Nick O'Leary" - }, - { - "name": "Dave Conway-Jones" - } - ], - "dependencies": { - "acorn": "8.7.0", - "acorn-walk": "8.2.0", - "ajv": "8.10.0", - "async-mutex": "0.3.2", - "basic-auth": "2.0.1", - "bcryptjs": "2.4.3", - "body-parser": "1.19.1", - "cheerio": "1.0.0-rc.10", - "clone": "2.1.2", - "content-type": "1.0.4", - "cookie": "0.4.2", - "cookie-parser": "1.4.6", - "cors": "2.8.5", - "cronosjs": "1.7.1", - "denque": "2.0.1", - "express": "4.17.2", - "express-session": "1.17.2", - "form-data": "4.0.0", - "fs-extra": "10.0.0", - "fs.notify": "0.0.4", - "got": "11.8.3", - "hash-sum": "2.0.0", - "hpagent": "0.1.2", - "https-proxy-agent": "5.0.0", - "i18next": "21.6.11", - "iconv-lite": "0.6.3", - "is-utf8": "0.2.1", - "js-yaml": "3.14.1", - "json-stringify-safe": "5.0.1", - "jsonata": "1.8.6", - "lodash.clonedeep": "^4.5.0", - "media-typer": "1.1.0", - "memorystore": "1.6.7", - "mime": "3.0.0", - "moment-timezone": "0.5.34", - "mqtt": "4.3.5", - "multer": "1.4.4", - "mustache": "4.2.0", - "node-red": "2.2.3", - "node-red-admin": "^2.2.3", - "node-red-contrib-pythonshell": "github:namgk/node-red-contrib-pythonshell", - "nopt": "5.0.0", - "oauth2orize": "1.11.1", - "on-headers": "1.0.2", - "passport": "0.5.2", - "passport-http-bearer": "1.0.1", - "passport-oauth2-client-password": "0.1.2", - "raw-body": "2.4.3", - "semver": "7.3.5", - "tar": "6.1.11", - "tough-cookie": "4.0.0", - "uglify-js": "3.15.1", - "uuid": "8.3.2", - "ws": "7.5.6", - "xml2js": "0.4.23" - }, - "optionalDependencies": { - "bcrypt": "5.0.1" - }, - "devDependencies": { - "dompurify": "2.3.6", - "grunt": "1.5.2", - "grunt-chmod": "~1.1.1", - "grunt-cli": "~1.4.3", - "grunt-concurrent": "3.0.0", - "grunt-contrib-clean": "~2.0.0", - "grunt-contrib-compress": "2.0.0", - "grunt-contrib-concat": "~1.0.1", - "grunt-contrib-copy": "~1.0.0", - "grunt-contrib-jshint": "3.1.1", - "grunt-contrib-uglify": "5.0.1", - "grunt-contrib-watch": "~1.1.0", - "grunt-jsdoc": "2.4.1", - "grunt-jsdoc-to-markdown": "6.0.0", - "grunt-jsonlint": "2.1.3", - "grunt-mkdir": "~1.1.0", - "grunt-npm-command": "~0.1.2", - "grunt-sass": "~3.1.0", - "grunt-simple-mocha": "~0.4.1", - "grunt-simple-nyc": "^3.0.1", - "i18next-http-backend": "1.3.2", - "jquery-i18next": "1.2.1", - "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", - "marked": "4.0.12", - "minami": "1.2.3", - "mocha": "9.2.0", - "node-red-node-test-helper": "^0.2.7", - "nodemon": "2.0.15", - "proxy": "^1.0.2", - "sass": "1.49.7", - "should": "13.2.3", - "sinon": "11.1.2", - "stoppable": "^1.1.0", - "supertest": "6.2.2" - }, - "engines": { - "node": ">=12" - } -} diff --git a/kubeflow/examples/run.sh b/kubeflow/examples/run.sh deleted file mode 100644 index daca187e0..000000000 --- a/kubeflow/examples/run.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -target=$1 - -if [ "$#" -eq 1 ] -then - USERDIR=/data/$target -else - USERDIR=/data/0.helloworld -fi - -echo "run with userdir=$USERDIR" - -USERDIR=$USERDIR docker compose up -#USERDIR=$USERDIR docker compose convert diff --git a/kubeflow/examples/scripts/entrypoint.sh b/kubeflow/examples/scripts/entrypoint.sh deleted file mode 100644 index 705054c0a..000000000 --- a/kubeflow/examples/scripts/entrypoint.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -trap stop SIGINT SIGTERM - -function stop() { - kill $CHILD_PID - wait $CHILD_PID -} - -/usr/local/bin/node $NODE_OPTIONS node_modules/node-red/red.js --userDir $USERDIR & - -CHILD_PID="$!" - -wait "${CHILD_PID}" From 76e882ed0b4f70a44d4aae029ef6dc7d286e5db1 Mon Sep 17 00:00:00 2001 From: NootNoot0 <161794667+NootNoot0@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:01:01 +0800 Subject: [PATCH 3/3] Add files via upload --- Tunghai-CS-project-main/README.md | 61 + Tunghai-CS-project-main/kubeflow/LICENSE | 201 + Tunghai-CS-project-main/kubeflow/README.md | 354 + .../kubeflow/examples/0.helloworld/flows.json | 101 + .../examples/0.helloworld/flows_cred.json | 3 + .../examples/0.helloworld/helloworld.py | 6 + .../examples/0.helloworld/package.json | 6 + .../examples/0.helloworld/settings.js | 498 + .../examples/1.connect-kubeflow/flows.json | 368 + .../1.connect-kubeflow/flows_cred.json | 3 + .../node_modules/nodepipe/LSTM.html | 149 + .../node_modules/nodepipe/LSTM.js | 66 + .../node_modules/nodepipe/LSTM0.js | 147 + .../node_modules/nodepipe/decisionTree0.js | 147 + .../node_modules/nodepipe/decisiontree.html | 149 + .../node_modules/nodepipe/decisiontree.js | 66 + .../node_modules/nodepipe/fl.html | 149 + .../node_modules/nodepipe/fl.js | 66 + .../node_modules/nodepipe/fl0.js | 147 + .../node_modules/nodepipe/mnist.html | 149 + .../node_modules/nodepipe/mnist.js | 66 + .../node_modules/nodepipe/mnist0.js | 147 + .../node_modules/nodepipe/package.json | 30 + .../examples/1.connect-kubeflow/package.json | 6 + .../examples/1.connect-kubeflow/py/LSTM.py | 132 + .../examples/1.connect-kubeflow/py/README.md | 18 + .../py/__pycache__/kfp_login.cpython-38.pyc | Bin 0 -> 1992 bytes .../py/__pycache__/kfp_login.cpython-39.pyc | Bin 0 -> 2016 bytes .../__pycache__/kfp_namespace.cpython-38.pyc | Bin 0 -> 944 bytes .../__pycache__/kfp_namespace.cpython-39.pyc | Bin 0 -> 942 bytes .../py/api_examples/create_experiment.py | 59 + .../py/api_examples/create_run.py | 58 + .../py/api_examples/delete_experiment.py | 51 + .../py/api_examples/delete_pipeline.py | 50 + .../py/api_examples/delete_run.py | 50 + .../py/api_examples/get_run.py | 64 + .../py/api_examples/kfp_login.py | 93 + .../py/api_examples/kfp_namespace.py | 19 + .../py/api_examples/list_experiments.py | 44 + .../py/api_examples/list_pipelines.py | 43 + .../py/api_examples/upload_pipeline.py | 52 + .../1.connect-kubeflow/py/decisionTree.py | 132 + .../examples/1.connect-kubeflow/py/fl.py | 132 + .../1.connect-kubeflow/py/helloworld.py | 6 + .../examples/1.connect-kubeflow/py/install.py | 23 + .../1.connect-kubeflow/py/kfp_example.py | 44 + .../1.connect-kubeflow/py/kfp_login.py | 93 + .../1.connect-kubeflow/py/kfp_namespace.py | 19 + .../examples/1.connect-kubeflow/py/mnist.py | 132 + .../py/pipelines/LSTM_pipeline.yaml | 651 + .../py/pipelines/fl_pipeline.yaml | 639 + .../py/pipelines/mnist_pipeline.yaml | 211 + .../py/pipelines/only_decision_tree.yaml | 131 + .../py/pipelines/three-pipeline.yaml | 229 + .../1.connect-kubeflow/py/requirements.txt | 2 + .../examples/1.connect-kubeflow/settings.js | 498 + .../kubeflow/examples/Dockerfile | 20 + .../kubeflow/examples/README.md | 40 + .../kubeflow/examples/build.sh | 3 + .../kubeflow/examples/docker-compose.yaml | 33 + .../kubeflow/examples/package-lock.json | 10782 ++++++++++++++++ .../kubeflow/examples/package.json | 127 + .../kubeflow/examples/run.sh | 15 + .../kubeflow/examples/scripts/entrypoint.sh | 14 + 64 files changed, 17794 insertions(+) create mode 100644 Tunghai-CS-project-main/README.md create mode 100644 Tunghai-CS-project-main/kubeflow/LICENSE create mode 100644 Tunghai-CS-project-main/kubeflow/README.md create mode 100644 Tunghai-CS-project-main/kubeflow/examples/0.helloworld/flows.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/0.helloworld/flows_cred.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/0.helloworld/helloworld.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/0.helloworld/package.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/0.helloworld/settings.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/flows.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/flows_cred.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.html create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/package.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/LSTM.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/README.md create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/fl.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/helloworld.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/install.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/mnist.py create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/requirements.txt create mode 100644 Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/settings.js create mode 100644 Tunghai-CS-project-main/kubeflow/examples/Dockerfile create mode 100644 Tunghai-CS-project-main/kubeflow/examples/README.md create mode 100644 Tunghai-CS-project-main/kubeflow/examples/build.sh create mode 100644 Tunghai-CS-project-main/kubeflow/examples/docker-compose.yaml create mode 100644 Tunghai-CS-project-main/kubeflow/examples/package-lock.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/package.json create mode 100644 Tunghai-CS-project-main/kubeflow/examples/run.sh create mode 100644 Tunghai-CS-project-main/kubeflow/examples/scripts/entrypoint.sh diff --git a/Tunghai-CS-project-main/README.md b/Tunghai-CS-project-main/README.md new file mode 100644 index 000000000..ee30e018e --- /dev/null +++ b/Tunghai-CS-project-main/README.md @@ -0,0 +1,61 @@ +目的 : + +這是一個node-red搭配kubeflow的作品,node-red作為畫面顯示,而kubeflow則是資料處理。在這個作品我將LSTM、mnist節點放在node-red,點擊該節點後,kubeflow則執行對應模型,模型所使用的輸入資料是normal.csv & abnormal.csv,輸出則是資料經模型訓練後的準確度。 + +安裝 : + +1. 將檔案 git clone 到 windows/System32 +2. 執行 Docker +3. 執行 Wsl 並依序輸入 cd kube-nodered, cd examples, 最後是 ./run.sh 1.connect-kubeflow +4. 查 Docker 是否有生成的容器和映像檔 +5. 執行 Docker 映像檔並執行 node-red +6. 執行 node-red後, 點擊 'intsall dependency', 接著使用者可以在'six pipeline' 頁面執行模型 +7. 到路徑 kube-nodered\examples\1.connect-kubeflow\py 中調整目錄底下的模型Python檔案,將登錄帳密改為使用者的 +=============================================================================== + +架構 : + +客製化節點的關鍵在於更改.flows.json、加入js.和html到nodepipe資料夾、加入模型python到py資料夾和加入模型pipeline到pipeline資料夾。node-red顯示的部分 : .flow.json更改會影響node-red節點的顯示,nodepipe的js.和html可以客製一個節點的功能欄位,如下拉選單。Kubeflow執行的部分 : 模型的python和pipeline。 +以下是各個檔案的路徑 +1. C:\Windows\System32\kube-nodered\examples\1.connect-kubeflo的.flow.json +2. C:\Windows\System32\kube-nodered\examples\1.connect-kubeflow\node_modules\nodepipe的js.和html +3. C:\Windows\System32\kube-nodered\examples\1.connect-kubeflow\py的模型python +4. C:\Windows\System32\kube-nodered\examples\1.connect-kubeflow\py\pipelines的模型pipeline +5. +================================================================================ + +輸入和輸出 : + +輸入資料 +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/773957ef-5aeb-4321-b0b2-8dfd712c1356) +輸出結果 +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/721fba7b-5aaf-4539-bd54-9f40b4d63de8) + +================================================================================= + +操作說明 : + +打開node-red後,先點擊圖中按鈕,安裝所需套件 +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/653de771-bba0-4408-acbb-a5174e34475f) +點擊圖中圓圈,切換分頁到模型節點 +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/82516d3f-4c72-4ee0-89cf-79aa699ce51e) +切換後的分頁 +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/2b89c8cc-4c89-44d5-9a4a-52e69be2170e) +點擊圖中按鈕,kubeflow會執行對應pipeline +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/16fb3142-a75b-42e7-a7c3-13bb8b955765) +可在畫面右側確認執行狀況,圖中範例為LSTM pipeline正在執行 +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/90829686-8627-4304-9047-1151ac02f59f) +在node-red上點擊執行後,可在kubeflow上看到新增的執行pipeline +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/f6fd314e-7365-430c-978f-ca1ab0f18e18) +Kubeflow上的執行結果 +![image](https://github.com/NootNoot0/Tunghai-CS-project/assets/161794667/ba16438c-92bd-4f04-b369-b191abfd97f5) + + + + + + + + + + diff --git a/Tunghai-CS-project-main/kubeflow/LICENSE b/Tunghai-CS-project-main/kubeflow/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Tunghai-CS-project-main/kubeflow/README.md b/Tunghai-CS-project-main/kubeflow/README.md new file mode 100644 index 000000000..ecdb567e3 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/README.md @@ -0,0 +1,354 @@ +# Kube-node-red(en) +[![hackmd-github-sync-badge](https://hackmd.io/cocSOGQMR-qzo7DHdwgRsQ/badge)](https://hackmd.io/cocSOGQMR-qzo7DHdwgRsQ) + +Kube-node-red is aiming to integrate Kubeflow/Kubebeters with node-red, leveraging node-red's low-code modules, and using Kubeflow resources (e.g. Kubeflow pipeline, Kserve) to enhance its AI/ML ability. +## Table of Contents + + +- [Installation](#installation) + * [Prerequisites](#Prerequisites) + * [Building](#Building) + * [Install dependencies](#Install-dependencies) +- [Using our nodes](#Using-our-nodes) +- [Test python files to interact with kubeflow](#Test-python-files-to-interact-with-kubeflow) +- [possible problems and solution](#possible-problems-and-solution) +- [Modify your own custom nodes/pipeline](#Modify-your-own-custom-nodes/pipeline) + * [Kubeflow part](#Kubeflow-part) + * [Node-red part](#Node-red-part) +- [Architecture](#Architecture) +- [Demo](#Demo) +- [Reference](#Reference) + + + +# Installation +## Prerequisites +- `Kubeflow` +As this project focused on the node-red integration with Kubeflow, one running Kubeflow instance should be ready on a publicly available network. +(If you need to provision your own Kubeflow instance, you could refer to our [mulitkf](https://github.com/footprintai/multikf) project to allocate one instance for developing.) +- [`WSL`](https://learn.microsoft.com/en-us/windows/wsl/install) If you are Windows OS. +- [`Docker`](https://www.docker.com) + +## Building + +We organized some examples under examples folder, and make sensitive information pass via environment variables. Please refer the following example to launch an individual example: + +1. In terminal (If you on Windows system, please use WSL) +``` +$ git clone https://github.com/NightLightTw/kube-nodered.git +``` +2. Enter target folder +``` +cd kube-nodered/examples +``` +3. Enter account information and start +``` +KUBEFLOW_HOST= \ +KUBEFLOW_USERNAME= \ +KUBEFLOW_PASSWORD= \ +./run.sh +``` +> **Info:** Here please use 1.connect-kubeflow + +## Install dependencies + +1. Then you can go to UI, check it out: http://127.0.0.1:1880/ +![](https://hackmd.io/_uploads/HJ8Rbmdya.png) + +2. Click the “install dependency” button to install dependency items such as specific python libraries and wait for its completion +![](https://hackmd.io/_uploads/rygsMmuy6.png) + +3. Click the “list experiments” button to test the environment work! +![](https://hackmd.io/_uploads/HyXxfX_kp.png) + +## Using our nodes +Switch to the "three-pipeline" flow and press the button to trigger the pipeline process + +![](https://hackmd.io/_uploads/Hkr4mXdk6.png) + +On kubeflow: +![](https://hackmd.io/_uploads/H1_hEX_JT.png) + + + +> **Info:** If the environment variable does not work, please fill in the account password directly in the python file + + +## Test python files to interact with kubeflow +``` +# Open another terminal and check docker status +docker ps +#enter container +docker exec -it bash +#enter document folder +cd /data/1.connect-kubeflow/py/api_examples +#execute function +python3 +``` + +You can test the file in api_example +> **Info:** Some of these files require a custom name, description, or assigned id in + +## Possible problems and solution +Q1: MissingSchema Invalid URL '' + +A1: This problem means that the login information is not accessed correctly, which may be caused by the environment variable not being read. +You can directly override the login information of the specified file + +ex:![](https://hackmd.io/_uploads/ryx59rejBh.jpg) + +Change to your own login information +``` +host = "https://example@test.com" +username = "test01" +password = "123456" +``` + +# Modify your own custom nodes/pipeline +![implementation architecture](https://hackmd.io/_uploads/H1ZLgUsH2.png) + +## Kubeflow part +### Custom make pipeline’s yaml file +Please refer to [Kubeflow implementation:add Random Forest algorithm](https://hackmd.io/@Nhi7So-lTz2m5R6pHyCLcA/Sk1eZFTbh) + +### Take changing randomForest.py as an example + +Modify using your own yaml file path +> **Info:** Line 66: uploadfile='pipelines/only_randomforest.yaml' + +> **Info:** Line 122~129 use json parser for filtering different outputs from get_run() + +```python= +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for only_randomforest." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/only_randomforest.yaml' + name='pipeline-' + random_suffix() + description="This is a only_randomForest pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'run_only_randomForest' + random_suffix() + description = "This is a only_randomForest run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'random-forest-classifier-Accuracy': #change parameter + output_value = parameter['value'] + + if output_value is not None: + print(f"Random Forest Classifier Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) +``` + +## Node-red part +**Package nodered pyshell node** + +**A node mainly consists of two files** +* **Javascript file(.js)** +define what the node does +* **HTML file(.html)** +Define the properties of the node and the windows and help messages in the Node-RED editor + +**When finally package into npm module, will need package.json** + + +### **package.json** +A standard file for describing the content of node.js modules + +A standard package.json can be generated using npm init. This command will ask a series of questions to find a reasonable default value. When asked for the name of the module name: enter the example name node-red-contrib- + +When it is established, you need to manually add the node-red attribute +*p.s. Where the example files need to be changed * + + + +```json= +{ + "name": "node-red-contrib-pythonshell-custom", + ... + "node-red": { + "nodes": { + "decisionTree": "decisiontree.js", + "randomForest": "randomforest.js", + "logisticRegression": "logisticregression.js" + "":"" + } + }, + ... +} + +``` +### **HTML** +```javascript= + + + + + + + \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js new file mode 100644 index 000000000..d16c5fe18 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM.js @@ -0,0 +1,66 @@ +/** + * Copyright 2014 Sense Tecnic Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var httpclient; +var PythonshellNode = require('./LSTM0'); + +module.exports = function(RED) { + "use strict"; + + function PythonshellInNode(n) { + RED.nodes.createNode(this,n); + + var node = this; + node.config = n; // copy config to the backend so that down bellow we can have a reference + + var pyNode = new PythonshellNode(n); + + pyNode.setStatusCallback(node.status.bind(node)) + + node.on("input",function(msg) { + pyNode.onInput(msg, function(result){ + node.send(result); + }, function(err){ + node.error(err); + }); + }); + + node.on('close', ()=>pyNode.onClose()); + } + + RED.nodes.registerType("LSTM", PythonshellInNode); + + RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + if (node.config.continuous){// see above comment + node.receive({payload: 'pythonshell@close'}) + } else { + node.receive(); + } + res.sendStatus(200); + } catch(err) { + res.sendStatus(500); + node.error(RED._("pythonshell.failed",{error:err.toString()})); + } + } else { + res.sendStatus(404); + } + }); + +} diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js new file mode 100644 index 000000000..86c0742f4 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/LSTM0.js @@ -0,0 +1,147 @@ +var fs = require("fs"); + +function PythonshellInNode(config) { + if (!config.pyfile){ + throw 'pyfile not present'; + } + this.pythonExec = config.python3 ? "python3" : "python"; + this.pyfile = '/data/1.connect-kubeflow/py/LSTM.py'; + this.virtualenv = config.virtualenv; + + if (!fs.existsSync(this.pyfile)) { + throw 'pyfile not exist'; + } + + if (this.virtualenv && !fs.existsSync(this.virtualenv)){ + throw 'configured virtualenv not exist, consider remove or change'; + } + + this.stdInData = config.stdInData; + this.continuous = this.stdInData ? true : config.continuous; + this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); + this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); + this.spawn = require('child_process').spawn; + this.onStatus = ()=>{} +} + +PythonshellInNode.prototype.onInput = function(msg, out, err) { + payload = msg.payload || ''; + if (typeof payload === 'object'){ + payload = JSON.stringify(payload); + } else if (typeof payload !== 'string'){ + payload = payload.toString(); + } + + if (payload === 'pythonshell@close'){ + if (this.py != null){ + this.onClose() + return + } else { + // trigger new execution + payload = '' + } + } + + if (this.continuous && !this.stdInData && this.py != null){ + this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) + return + } + + var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec + + if (this.stdInData){ + if (!this.py){ + this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { + cwd: this.pydir, + detached: true + }); + this.firstExecution = true + } else { + this.firstExecution = false + } + } else { + this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { + cwd: this.pydir + }); + } + + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + + // subsequence message, no need to setup callbacks + if (this.stdInData && !this.firstExecution){ + this.py.stdin.write(payload + '\n') + return + } + + var py = this.py; + var dataString = ''; + var errString = ''; + + py.stdout.on('data', data => { + clearTimeout(this.standbyTimer) + + this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) + + let dataStr = data.toString(); + + dataString += dataStr; + + if (dataString.endsWith("\n")){ + if (this.continuous){ + msg.payload = dataString; + out(msg); + dataString = '' + } + } + + this.standbyTimer = setTimeout(()=>{ + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + }, 2000) + + }); + + py.stderr.on('data', data => { + errString += String(data);// just a different way to do it + this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) + }); + + py.stderr.on('error', console.log) + py.stdout.on('error', console.log) + py.stdin.on('error', console.log) + py.on('error', console.log) + + py.on('close', code =>{ + if (code){ + err('exit code: ' + code + ', ' + errString); + this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) + } else if (!this.continuous){ + msg.payload = dataString.trim(); + out(msg); + this.onStatus({fill:"green",shape:"dot",text:"Done"}) + } else { + this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) + } + this.py = null + setTimeout(()=>{ + this.onStatus({}) + }, 2000) + }); + + if (this.stdInData){ + py.stdin.write(payload + '\n') + } +}; + +PythonshellInNode.prototype.onClose = function() { + if (this.py){ + this.py.kill() + this.py = null + } +}; + +PythonshellInNode.prototype.setStatusCallback = function(callback) { + this.onStatus = callback +}; + + +module.exports = PythonshellInNode \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js new file mode 100644 index 000000000..7a8f3a690 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisionTree0.js @@ -0,0 +1,147 @@ +var fs = require("fs"); + +function PythonshellInNode(config) { + if (!config.pyfile){ + throw 'pyfile not present'; + } + this.pythonExec = config.python3 ? "python3" : "python"; + this.pyfile = "/data/1.connect-kubeflow/py/decisionTree.py"; + this.virtualenv = config.virtualenv; + + if (!fs.existsSync(this.pyfile)) { + throw 'pyfile not exist'; + } + + if (this.virtualenv && !fs.existsSync(this.virtualenv)){ + throw 'configured virtualenv not exist, consider remove or change'; + } + + this.stdInData = config.stdInData; + this.continuous = this.stdInData ? true : config.continuous; + this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); + this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); + this.spawn = require('child_process').spawn; + this.onStatus = ()=>{} +} + +PythonshellInNode.prototype.onInput = function(msg, out, err) { + payload = msg.payload || ''; + if (typeof payload === 'object'){ + payload = JSON.stringify(payload); + } else if (typeof payload !== 'string'){ + payload = payload.toString(); + } + + if (payload === 'pythonshell@close'){ + if (this.py != null){ + this.onClose() + return + } else { + // trigger new execution + payload = '' + } + } + + if (this.continuous && !this.stdInData && this.py != null){ + this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) + return + } + + var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec + + if (this.stdInData){ + if (!this.py){ + this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { + cwd: this.pydir, + detached: true + }); + this.firstExecution = true + } else { + this.firstExecution = false + } + } else { + this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { + cwd: this.pydir + }); + } + + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + + // subsequence message, no need to setup callbacks + if (this.stdInData && !this.firstExecution){ + this.py.stdin.write(payload + '\n') + return + } + + var py = this.py; + var dataString = ''; + var errString = ''; + + py.stdout.on('data', data => { + clearTimeout(this.standbyTimer) + + this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) + + let dataStr = data.toString(); + + dataString += dataStr; + + if (dataString.endsWith("\n")){ + if (this.continuous){ + msg.payload = dataString; + out(msg); + dataString = '' + } + } + + this.standbyTimer = setTimeout(()=>{ + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + }, 2000) + + }); + + py.stderr.on('data', data => { + errString += String(data);// just a different way to do it + this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) + }); + + py.stderr.on('error', console.log) + py.stdout.on('error', console.log) + py.stdin.on('error', console.log) + py.on('error', console.log) + + py.on('close', code =>{ + if (code){ + err('exit code: ' + code + ', ' + errString); + this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) + } else if (!this.continuous){ + msg.payload = dataString.trim(); + out(msg); + this.onStatus({fill:"green",shape:"dot",text:"Done"}) + } else { + this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) + } + this.py = null + setTimeout(()=>{ + this.onStatus({}) + }, 2000) + }); + + if (this.stdInData){ + py.stdin.write(payload + '\n') + } +}; + +PythonshellInNode.prototype.onClose = function() { + if (this.py){ + this.py.kill() + this.py = null + } +}; + +PythonshellInNode.prototype.setStatusCallback = function(callback) { + this.onStatus = callback +}; + + +module.exports = PythonshellInNode \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html new file mode 100644 index 000000000..2045d7745 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.html @@ -0,0 +1,149 @@ +f + + + + + + + \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js new file mode 100644 index 000000000..1727299e0 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/decisiontree.js @@ -0,0 +1,66 @@ +/** + * Copyright 2014 Sense Tecnic Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var httpclient; +var PythonshellNode = require('./decisionTree0'); + +module.exports = function(RED) { + "use strict"; + + function PythonshellInNode(n) { + RED.nodes.createNode(this,n); + + var node = this; + node.config = n; // copy config to the backend so that down bellow we can have a reference + + var pyNode = new PythonshellNode(n); + + pyNode.setStatusCallback(node.status.bind(node)) + + node.on("input",function(msg) { + pyNode.onInput(msg, function(result){ + node.send(result); + }, function(err){ + node.error(err); + }); + }); + + node.on('close', ()=>pyNode.onClose()); + } + + RED.nodes.registerType("decisionTree", PythonshellInNode); + + RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + if (node.config.continuous){// see above comment + node.receive({payload: 'pythonshell@close'}) + } else { + node.receive(); + } + res.sendStatus(200); + } catch(err) { + res.sendStatus(500); + node.error(RED._("pythonshell.failed",{error:err.toString()})); + } + } else { + res.sendStatus(404); + } + }); + +} diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html new file mode 100644 index 000000000..35f46a295 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.html @@ -0,0 +1,149 @@ +f + + + + + + + \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js new file mode 100644 index 000000000..edabfa19e --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl.js @@ -0,0 +1,66 @@ +/** + * Copyright 2014 Sense Tecnic Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var httpclient; +var PythonshellNode = require('./fl0'); + +module.exports = function(RED) { + "use strict"; + + function PythonshellInNode(n) { + RED.nodes.createNode(this,n); + + var node = this; + node.config = n; // copy config to the backend so that down bellow we can have a reference + + var pyNode = new PythonshellNode(n); + + pyNode.setStatusCallback(node.status.bind(node)) + + node.on("input",function(msg) { + pyNode.onInput(msg, function(result){ + node.send(result); + }, function(err){ + node.error(err); + }); + }); + + node.on('close', ()=>pyNode.onClose()); + } + + RED.nodes.registerType("fl", PythonshellInNode); + + RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + if (node.config.continuous){// see above comment + node.receive({payload: 'pythonshell@close'}) + } else { + node.receive(); + } + res.sendStatus(200); + } catch(err) { + res.sendStatus(500); + node.error(RED._("pythonshell.failed",{error:err.toString()})); + } + } else { + res.sendStatus(404); + } + }); + +} diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js new file mode 100644 index 000000000..ee8b3f222 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/fl0.js @@ -0,0 +1,147 @@ +var fs = require("fs"); + +function PythonshellInNode(config) { + if (!config.pyfile){ + throw 'pyfile not present'; + } + this.pythonExec = config.python3 ? "python3" : "python"; + this.pyfile = "/data/1.connect-kubeflow/py/fl.py"; + this.virtualenv = config.virtualenv; + + if (!fs.existsSync(this.pyfile)) { + throw 'pyfile not exist'; + } + + if (this.virtualenv && !fs.existsSync(this.virtualenv)){ + throw 'configured virtualenv not exist, consider remove or change'; + } + + this.stdInData = config.stdInData; + this.continuous = this.stdInData ? true : config.continuous; + this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); + this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); + this.spawn = require('child_process').spawn; + this.onStatus = ()=>{} +} + +PythonshellInNode.prototype.onInput = function(msg, out, err) { + payload = msg.payload || ''; + if (typeof payload === 'object'){ + payload = JSON.stringify(payload); + } else if (typeof payload !== 'string'){ + payload = payload.toString(); + } + + if (payload === 'pythonshell@close'){ + if (this.py != null){ + this.onClose() + return + } else { + // trigger new execution + payload = '' + } + } + + if (this.continuous && !this.stdInData && this.py != null){ + this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) + return + } + + var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec + + if (this.stdInData){ + if (!this.py){ + this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { + cwd: this.pydir, + detached: true + }); + this.firstExecution = true + } else { + this.firstExecution = false + } + } else { + this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { + cwd: this.pydir + }); + } + + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + + // subsequence message, no need to setup callbacks + if (this.stdInData && !this.firstExecution){ + this.py.stdin.write(payload + '\n') + return + } + + var py = this.py; + var dataString = ''; + var errString = ''; + + py.stdout.on('data', data => { + clearTimeout(this.standbyTimer) + + this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) + + let dataStr = data.toString(); + + dataString += dataStr; + + if (dataString.endsWith("\n")){ + if (this.continuous){ + msg.payload = dataString; + out(msg); + dataString = '' + } + } + + this.standbyTimer = setTimeout(()=>{ + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + }, 2000) + + }); + + py.stderr.on('data', data => { + errString += String(data);// just a different way to do it + this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) + }); + + py.stderr.on('error', console.log) + py.stdout.on('error', console.log) + py.stdin.on('error', console.log) + py.on('error', console.log) + + py.on('close', code =>{ + if (code){ + err('exit code: ' + code + ', ' + errString); + this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) + } else if (!this.continuous){ + msg.payload = dataString.trim(); + out(msg); + this.onStatus({fill:"green",shape:"dot",text:"Done"}) + } else { + this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) + } + this.py = null + setTimeout(()=>{ + this.onStatus({}) + }, 2000) + }); + + if (this.stdInData){ + py.stdin.write(payload + '\n') + } +}; + +PythonshellInNode.prototype.onClose = function() { + if (this.py){ + this.py.kill() + this.py = null + } +}; + +PythonshellInNode.prototype.setStatusCallback = function(callback) { + this.onStatus = callback +}; + + +module.exports = PythonshellInNode \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html new file mode 100644 index 000000000..322e0e99d --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.html @@ -0,0 +1,149 @@ +f + + + + + + + \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js new file mode 100644 index 000000000..3c3e04c13 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist.js @@ -0,0 +1,66 @@ +/** + * Copyright 2014 Sense Tecnic Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var httpclient; +var PythonshellNode = require('./mnist0'); + +module.exports = function(RED) { + "use strict"; + + function PythonshellInNode(n) { + RED.nodes.createNode(this,n); + + var node = this; + node.config = n; // copy config to the backend so that down bellow we can have a reference + + var pyNode = new PythonshellNode(n); + + pyNode.setStatusCallback(node.status.bind(node)) + + node.on("input",function(msg) { + pyNode.onInput(msg, function(result){ + node.send(result); + }, function(err){ + node.error(err); + }); + }); + + node.on('close', ()=>pyNode.onClose()); + } + + RED.nodes.registerType("mnist", PythonshellInNode); + + RED.httpAdmin.post("/pythonshell/:id", RED.auth.needsPermission("pythonshell.query"), function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + if (node.config.continuous){// see above comment + node.receive({payload: 'pythonshell@close'}) + } else { + node.receive(); + } + res.sendStatus(200); + } catch(err) { + res.sendStatus(500); + node.error(RED._("pythonshell.failed",{error:err.toString()})); + } + } else { + res.sendStatus(404); + } + }); + +} diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js new file mode 100644 index 000000000..58ebc34a3 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/mnist0.js @@ -0,0 +1,147 @@ +var fs = require("fs"); + +function PythonshellInNode(config) { + if (!config.pyfile){ + throw 'pyfile not present'; + } + this.pythonExec = config.python3 ? "python3" : "python"; + this.pyfile = "/data/1.connect-kubeflow/py/mnist.py"; + this.virtualenv = config.virtualenv; + + if (!fs.existsSync(this.pyfile)) { + throw 'pyfile not exist'; + } + + if (this.virtualenv && !fs.existsSync(this.virtualenv)){ + throw 'configured virtualenv not exist, consider remove or change'; + } + + this.stdInData = config.stdInData; + this.continuous = this.stdInData ? true : config.continuous; + this.pydir = this.pyfile.substring(0, this.pyfile.lastIndexOf('/')); + this.pyfile = this.pyfile.substring(this.pyfile.lastIndexOf('/') + 1, this.pyfile.length); + this.spawn = require('child_process').spawn; + this.onStatus = ()=>{} +} + +PythonshellInNode.prototype.onInput = function(msg, out, err) { + payload = msg.payload || ''; + if (typeof payload === 'object'){ + payload = JSON.stringify(payload); + } else if (typeof payload !== 'string'){ + payload = payload.toString(); + } + + if (payload === 'pythonshell@close'){ + if (this.py != null){ + this.onClose() + return + } else { + // trigger new execution + payload = '' + } + } + + if (this.continuous && !this.stdInData && this.py != null){ + this.onStatus({fill:"yellow",shape:"dot",text:"Not accepting input"}) + return + } + + var spawnCmd = (this.virtualenv ? this.virtualenv + '/bin/' : '') + this.pythonExec + + if (this.stdInData){ + if (!this.py){ + this.py = this.spawn(spawnCmd, ['-u', this.pyfile], { + cwd: this.pydir, + detached: true + }); + this.firstExecution = true + } else { + this.firstExecution = false + } + } else { + this.py = this.spawn(spawnCmd, ['-u', this.pyfile, payload], { + cwd: this.pydir + }); + } + + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + + // subsequence message, no need to setup callbacks + if (this.stdInData && !this.firstExecution){ + this.py.stdin.write(payload + '\n') + return + } + + var py = this.py; + var dataString = ''; + var errString = ''; + + py.stdout.on('data', data => { + clearTimeout(this.standbyTimer) + + this.onStatus({fill:"green",shape:"dot",text:"Processing data"}) + + let dataStr = data.toString(); + + dataString += dataStr; + + if (dataString.endsWith("\n")){ + if (this.continuous){ + msg.payload = dataString; + out(msg); + dataString = '' + } + } + + this.standbyTimer = setTimeout(()=>{ + this.onStatus({fill:"green",shape:"dot",text:"Standby"}) + }, 2000) + + }); + + py.stderr.on('data', data => { + errString += String(data);// just a different way to do it + this.onStatus({fill:"red",shape:"dot",text:"Error: " + errString}) + }); + + py.stderr.on('error', console.log) + py.stdout.on('error', console.log) + py.stdin.on('error', console.log) + py.on('error', console.log) + + py.on('close', code =>{ + if (code){ + err('exit code: ' + code + ', ' + errString); + this.onStatus({fill:"red",shape:"dot",text:"Exited: " + code}) + } else if (!this.continuous){ + msg.payload = dataString.trim(); + out(msg); + this.onStatus({fill:"green",shape:"dot",text:"Done"}) + } else { + this.onStatus({fill:"yellow",shape:"dot",text:"Script Closed"}) + } + this.py = null + setTimeout(()=>{ + this.onStatus({}) + }, 2000) + }); + + if (this.stdInData){ + py.stdin.write(payload + '\n') + } +}; + +PythonshellInNode.prototype.onClose = function() { + if (this.py){ + this.py.kill() + this.py = null + } +}; + +PythonshellInNode.prototype.setStatusCallback = function(callback) { + this.onStatus = callback +}; + + +module.exports = PythonshellInNode \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json new file mode 100644 index 000000000..fcf46cd21 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/node_modules/nodepipe/package.json @@ -0,0 +1,30 @@ +{ + "name": "node-red-contrib-pythonshell-custom", + "version": "1.0.0", + "description": "modified version of node-red-contrib-pythonshell with additional features", + "scripts": { + "test": "./node_modules/mocha/bin/mocha" + }, + "keywords": [ + "distributed", + "python", + "node", + "node-red" + ], + "author": "WuChunYen", + "license": "ISC", + "dependencies": {}, + "node-red": { + "nodes": { + "decisionTree": "decisiontree.js", + "randomForest": "randomforest.js", + "logisticRegression": "logisticregression.js", + "fl": "fl.js", + "mnist": "mnist.js", + "LSTM": "LSTM.js" + } + }, + "devDependencies": { + "mocha": "^5.0.4" + } +} diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/package.json b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/package.json new file mode 100644 index 000000000..b788fd491 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/package.json @@ -0,0 +1,6 @@ +{ + "name": "node-red-project", + "description": "A Node-RED Project", + "version": "0.0.1", + "private": true +} \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/LSTM.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/LSTM.py new file mode 100644 index 000000000..0eb2cb76a --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/LSTM.py @@ -0,0 +1,132 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "https://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for LSTM." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/LSTM_pipeline.yaml' + name='pipeline-' + random_suffix() + description="This is a LSTM pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'LSTM' + random_suffix() + description = "This is a LSTM run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'random-forest-classifier-Accuracy': #change parameter + output_value = parameter['value'] + + if output_value is not None: + print(f"Random Forest Classifier Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/README.md b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/README.md new file mode 100644 index 000000000..06bb167e4 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/README.md @@ -0,0 +1,18 @@ +## How to use +``` +KUBEFLOW_HOST= \ +KUBEFLOW_USERNAME= \ +KUBEFLOW_PASSWORD= \ +python3 +``` +## three pipelines +流程架構: +create_experiment -> upload_pipeline -> create_run -> get_run -> filter -> result +### decisionTree.py +功能:以乳癌資料集訓練decisionTree模型並回傳準確率 + +### logisticRegression.py +功能:以乳癌資料集訓練logisticRegression模型並回傳準確率 + +### randomForest.py +功能:以乳癌資料集訓練randomForest模型並回傳準確率 diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..193a91af9ab988978f2373b5b3ad1d940277f916 GIT binary patch literal 1992 zcmah}&2JM&6rb5IZ=AIg0;F(h=YRx`iqlH%#dQ(1Q2G(2Aqh$qR5|ONak9>OXPKEL z#Bwf$V^QguR7%uS@BJfs?0K*4g@1txrEg|!6rfUPwe#`jz2Cg=yR}*s!MJn%9{aJ5 z&|ms+dbn`74!`^eCWQUXVas24K=*yAc>Y6 zxbSn4$SjFf!zpao13@y8h67gkSt#Wm7qsvMQ@KbZTT6{c1y-%*=kUu17@-j;GXAVX z_rO-@2p^-T_@~taXXNxPxVNeE#5!+9^oG_P~4GC z{Weniw(x`-a(15ZsIRcSEt`qRgj z_#M^&C^Z_;nxWaW{$#>6Gv@kp(I0iDjaQTmzD*-+lp`zaRwYnmIbH?#)~K$y{J z7tsihEPCe90;IVo_JMoaESfq@3N+Qm8W7agl8#h*$zgoWCB0Nn>$t|fu6-O)M43S#~YisG|jTPAD z@OTQ>zye62U<95OKmuu*XBiiYQG=}2Hsi`3Bb4>RJW;P!P%D>lx=r4G4GipZwPUbZ z8g>&!kY%0dwi2&8h0e3N%sFX4M&lz6~|_QLxlPNO8J8a5ML@rWm{$&ItWWgPVO z!(5QDm6JL-Ej_82|CgR{meOT?wT$OpMIcUlTnvm44cBtR-3(YtGajd^qiZ#QSjK`y z<*7#5!%o7tS*Uh~GbORP z0CZ6AlJG&KVHK`93f<4(YwM8GEi$w|A(7T`GA!8W$JXGN@4~bVUF-Y#13bcg=spzcw2z?z z?Vqjt4%8NYfj`xXnRe*Hi#da%)%>8q(Qinc2ZR?_7PZ=oA2uVNrVxs&yW^x=%=Q;| zds!KgX0~5c+es`{#0S~6ds+bpCJ!3faABLN4qU~&qn!v*GbPw;8!yUhu$c%7-Etdq zg)i9soJl2%%38@?*nm<@m!X3=Q&t44IXG{?ZVADK(9OHB6P6a09f0FvUub_6mSBY^ zStz0%QPTt;k|ImOh!wWXyM+h1I@z3zOI0|1$iAXd=8X$uN03r8@S zZO%?&q*JrQyM5!la+=qV&i}U$behRkm{85acLTd_ zIktGLfte2iU3$)f55|Eg2qzwBht#$B)QQdD3IL#AwO{bdlVDfQb`S!olK{pft literal 0 HcmV?d00001 diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_login.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37989316f586bdf924c9c0c085096deb6c4817a1 GIT binary patch literal 2016 zcmah~&u<(x6t-tPvzyKCCQaKwFUW^V?H0OeB~HsywUAJLR3S8hid3+j9eb16%#NqF zr)i>zgh-DR%DF{Kj{F1s4V*d76)rvZR)oT{XSYgQBs>~>{QTbM=l8wm2^x(Wg7(GL z+x&+nLVudc@#ewgD!l4l=on%+M(bvDVmxxz9bC%Xb(a(Sc+7o57-8N6vhFjyidz0t zutdu(TvRg|t2B;uixe(=gFtba1S4Kl(?F?hAz9%|t}~g0uCW@o3XD~FKZIBPh!M)c zk@4d^@%CJe4)7s*gn#;WkK|bDF=CY*Jx0Hfef&KJ ziI=;q+C|!|R`xNQ+Hz#hY9O8NqTIcO9N3K@g7#gERsp$O(N$x22JPcLUr!y>SUvZL z(}#}y4aPc18m!J5R_3zi!->|+SnH46KWH8TKAY{Lc-sQsx^{EeZ za4S<$vO!7{ss(NdvvPJ5vhV7eEf~ot5T7X*q>wr_$VWFe5C`ft)sIOE-)j4Z%B;NI|UV zHit9<#`-|^4v=^+h$BWX(q%y>XQ06V3V^PBzPbh}-J!eAdo(mYPMQNBX0ugz)mzYQ zz-{);{2tEn5N;&~)jPycm+sHbT>`a*pX2w9WA>W#V8@KZ)M;NTaQG{drvc&l`32+l z!sT`-k_4!@xHV3?g>+|OYmkSi2HsF}?qJA@jz>WBlltM~#p%-q< zlcKT-a6;}#6N|!;yzmtdWVk6CMo@)>NaG;ng{!iD;RCKoG?EIX3o?YvD=K9UsaD0p zN&Tc5^xOwEmYSWv;bQT!uvMEs5;-v(qj z1cjlfgKKfrZ^PvQ7l4V4JY(dp(h?Fg3bj=~=D8tXTKB8nkziTOub5O*K6F)FcdG8c DjCnfW literal 0 HcmV?d00001 diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d49512c6312c4543713547c31315654ef7d280c6 GIT binary patch literal 944 zcmZuuO-~y!5cSuFBqRudgvh1Z8;Vqtw#O<(NCmYg)Ry#;s*1L2Cv38@7uyR;w2`X9 zwTGT*RXFya^f&n06MumVolQ#M(2?fZV|&Ik@4c^9%Lwf4?g#OcAoM2>9vXvS7u-Ap z;E3ZGb>=JXV2DXfMzljQ5=>CRIQ>pJ(3EDFlN!3DoL=E6 zvn*qr)zBHn2zFi#WpsYhLe?7;GLlhV_)4Z;<_(tk(va$bE%IU>T_9e{$OZbr&hQt^ z%Y6A9W!`1!3h_z}?Lkc#sCqEj2$HCIs`Rk0Rhl$~JlT$9Pq~$UlXOF+hLO0zFEoah zuX6wbmgdLi`ZvUrwb$+T8{gQ#rp6By7yi~{ear7D?Z4V@`$0d5q_NNaFwefToSIyb zLvZ5*^ihUBZcZ_ffNDU>kZ3k1a>}Ro5NnxT@+{}V^?m)k+Go~B|B?*OSxPH zL~!MHvIT1DNSuiK4AW@EDhy(?1Dm@%S6);!^|B+%IF!6t}vRUsUJ1 zbgdc+3BPL~=$;Y13UA!{f2PTYH5&j3uMmb;a0RadmNCJrw~XpXa04Bz!=g6uf&19JUS8RN5`{sO@%_O$>2 literal 0 HcmV?d00001 diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/__pycache__/kfp_namespace.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c29c28cec6281c9c0c84d4df70e3ff04056ed1e GIT binary patch literal 942 zcmZuvO-~y!5cSuFBqRudgvh1Z8;VqtmSdG7q=MQLYD-S3s%X1*!X_JgvAv)~8>uQ> zd+3=~g=7Coe}k_*@fWzz*`x#x9m&t0wP)tdn+>YfG6H+I_d)z52>r>O$Hu_fgJpIA zIN~@)o%xPC7<>|w5$#Zn1QS#+PQO#mxOc%i9>+(hUbulcbXdo()E*~-??<7nQ^$^# zv91!N_PA?=F_Dt4poLAf41vbN3UKmZy@F*v16VY`S0n=>*JMf}G^H8lq=v32r`LGO zEXx>YHFS zBUr`<=%WmM+?-+%0o6d1A<=9u$TxDrfG+JYtzzLkbtZ*&B^iu_NrF)PLUrOua3ZJo5NnxT_k8EV^?m)k+Go~CA(`mrJP$4 zSMDZTFiRbYQ}OWLG+MC=gV^lC;XcZh7x_%R?1(asC4oJ5Y@j0PJd?zcbzY()XKf#E&_l1n8@K+SZt_3VYycpq#ssh4F{+=y4KP@TO>Y9Yf*mK3 k?CX4njvA|HPac(;4PjQV*cvIG#$q?0y~!&TagkKWU&grhzW@LL literal 0 HcmV?d00001 diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py new file mode 100644 index 000000000..8ac8d7321 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_experiment.py @@ -0,0 +1,59 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="" # str | The ID of the name to be create. + description='' # str | The description experiment. + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + api_response = api_instance.create_experiment(body) + pprint(api_response) + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py new file mode 100644 index 000000000..b02691de7 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/create_run.py @@ -0,0 +1,58 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from pprint import pprint +from kfp_server_api.rest import ApiException +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.RunServiceApi(api_client) + pipeline_id = '' # str | The ID of the pipeline. + experiment_id = '' # str | The ID of the experiment. + display_name = '' # str | The name of the run to be create. + description = '' # str | The description of run. + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + + try: + # Creates a new run. + api_response = api_instance.create_run(body) + pprint(api_response) + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py new file mode 100644 index 000000000..31d9205c7 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_experiment.py @@ -0,0 +1,51 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.ExperimentServiceApi(api_client) + experiment_id = '' # str | The ID of the experiment to be deleted. + + try: + # Deletes an experiment without deleting the experiment's runs and recurring runs. + # To avoid unexpected behaviors, delete an experiment's runs and recurring runs before deleting the experiment. + api_response = api_instance.delete_experiment(experiment_id) + pprint(api_response) + except ApiException as e: + print("Exception when calling ExperimentServiceApi->delete_experiment: %s\n" % e) \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py new file mode 100644 index 000000000..c04d595ef --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_pipeline.py @@ -0,0 +1,50 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.PipelineServiceApi(api_client) + id = '' # str | The ID of the pipeline to be deleted. + + try: + # Deletes a pipeline and its pipeline versions. + api_response = api_instance.delete_pipeline(id) + pprint(api_response) + except ApiException as e: + print("Exception when calling PipelineServiceApi->delete_pipeline: %s\n" % e) \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py new file mode 100644 index 000000000..aefc7dca3 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/delete_run.py @@ -0,0 +1,50 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +import kfp +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.RunServiceApi(api_client) + id = '' # str | The ID of the run to be deleted. + + try: + # Deletes a run. + api_response = api_instance.delete_run(id) + pprint(api_response) + except ApiException as e: + print("Exception when calling RunServiceApi->delete_run: %s\n" % e) \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py new file mode 100644 index 000000000..f62c56bdc --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/get_run.py @@ -0,0 +1,64 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces +import json + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.RunServiceApi(api_client) + run_id = '' # str | The ID of the run to be retrieved. + + try: + # Finds a specific run by ID. + api_response = api_instance.get_run(run_id) + output = api_response.pipeline_runtime.workflow_manifest + output = json.loads(output) + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + output_value = None + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'decision-tree-classifier-Accuracy': + output_value = parameter['value'] + break + + if output_value is not None: + print(f"Decision Tree Classifier Accuracy: {output_value}") + else: + print("Parameter not found.") + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py new file mode 100644 index 000000000..7c95abcf0 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_login.py @@ -0,0 +1,93 @@ +import re +from urllib.parse import urlsplit + +import requests + +# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916 +def get_istio_auth_session(url: str, username: str, password: str) -> dict: + """ + Determine if the specified URL is secured by Dex and try to obtain a session cookie. + WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported + (we default default to using `staticPasswords` if both are enabled) + + :param url: Kubeflow server URL, including protocol + :param username: Dex `staticPasswords` or `LDAP` username + :param password: Dex `staticPasswords` or `LDAP` password + :return: auth session information + """ + # define the default return object + auth_session = { + "endpoint_url": url, # KF endpoint URL + "redirect_url": None, # KF redirect URL, if applicable + "dex_login_url": None, # Dex login URL (for POST of credentials) + "is_secured": None, # True if KF endpoint is secured + "session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2" + } + + # use a persistent session (for cookies) + with requests.Session() as s: + + ################ + # Determine if Endpoint is Secured + ################ + resp = s.get(url, allow_redirects=True) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {url}" + ) + + auth_session["redirect_url"] = resp.url + + # if we were NOT redirected, then the endpoint is UNSECURED + if len(resp.history) == 0: + auth_session["is_secured"] = False + return auth_session + else: + auth_session["is_secured"] = True + + ################ + # Get Dex Login URL + ################ + redirect_url_obj = urlsplit(auth_session["redirect_url"]) + + # if we are at `/auth?=xxxx` path, we need to select an auth type + if re.search(r"/auth$", redirect_url_obj.path): + # default to "staticPasswords" auth type + redirect_url_obj = redirect_url_obj._replace( + path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path) + ) + + # if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST) + if re.search(r"/auth/.*/login$", redirect_url_obj.path): + auth_session["dex_login_url"] = redirect_url_obj.geturl() + + # else, we need to be redirected to the actual login page + else: + # this GET should redirect us to the `/auth/xxxx/login` path + resp = s.get(redirect_url_obj.geturl(), allow_redirects=True) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}" + ) + + # set the login url + auth_session["dex_login_url"] = resp.url + + ################ + # Attempt Dex Login + ################ + resp = s.post( + auth_session["dex_login_url"], + data={"login": username, "password": password}, + allow_redirects=True + ) + if len(resp.history) == 0: + raise RuntimeError( + f"Login credentials were probably invalid - " + f"No redirect after POST to: {auth_session['dex_login_url']}" + ) + + # store the session cookies in a "key1=value1; key2=value2" string + auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies]) + + return auth_session \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py new file mode 100644 index 000000000..3c7c0dfdc --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/kfp_namespace.py @@ -0,0 +1,19 @@ +import os +import requests + +from typing import TypedDict + +def retrieve_namespaces(host: str, auth_session: TypedDict) -> str: + workgroup_endpoint = os.path.join(host, "api/workgroup/env-info") + + cookies = {} + cookie_tokens = auth_session["session_cookie"].split("=") + print(cookie_tokens[0]) + cookies[cookie_tokens[0]]=cookie_tokens[1] + resp = requests.get(workgroup_endpoint, cookies=cookies) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}" + ) + return [ns["namespace"] for ns in resp.json()["namespaces"] if + ns["role"]=="owner"] \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py new file mode 100644 index 000000000..2e4729bea --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_experiments.py @@ -0,0 +1,44 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.ExperimentServiceApi(api_client) + resource_reference_key_type = "NAMESPACE" + resource_reference_key_id = namespaces[0] + list_experiment_response = api_instance.list_experiment(resource_reference_key_type=resource_reference_key_type, resource_reference_key_id=resource_reference_key_id) + for experiment in list_experiment_response.experiments: + pprint(experiment) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py new file mode 100644 index 000000000..6e2be4b5e --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/list_pipelines.py @@ -0,0 +1,43 @@ +from __future__ import print_function +import string +import time +import kfp_server_api +import os +import requests +import kfp +import json +from pprint import pprint +from kfp_server_api.rest import ApiException +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + api_instance = kfp_server_api.PipelineServiceApi(api_client) + list_pipeline_response = api_instance.list_pipelines() + for pipelines in list_pipeline_response.pipelines: + print(pipelines) \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py new file mode 100644 index 000000000..410cf50aa --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/api_examples/upload_pipeline.py @@ -0,0 +1,52 @@ +from __future__ import print_function +import string +import random +import time +import kfp_server_api +import os +import requests +from kfp_server_api.rest import ApiException + +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + + +host = os.getenv("KUBEFLOW_HOST") +username = os.getenv("KUBEFLOW_USERNAME") +password = os.getenv("KUBEFLOW_PASSWORD") + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='' # The yaml file in your local path. + name='pipeline-' + random_suffix() + description='' # str | The description of pipeline. + try: + api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + print(api_response) + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py new file mode 100644 index 000000000..16293f1d6 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/decisionTree.py @@ -0,0 +1,132 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "http://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for only_decision_tree." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/only_decision_tree.yaml' + name='pipeline-' + random_suffix() + description="This is a only_decision_tree pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'run_only_decision_tree' + random_suffix() + description = "This is a only_decision_tree run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'decision-tree-classifier-Accuracy': + output_value = parameter['value'] + + if output_value is not None: + print(f"Decision Tree Classifier Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/fl.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/fl.py new file mode 100644 index 000000000..6aeb83f9d --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/fl.py @@ -0,0 +1,132 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "https://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for fl." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/fl_pipeline.yaml' + name='pipeline-' + random_suffix() + description="This is a fl pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'fl' + random_suffix() + description = "This is a fl run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'client-last_accuracy': + output_value = parameter['value'] + + if output_value is not None: + print(f"fl Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/helloworld.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/helloworld.py new file mode 100644 index 000000000..97e823fb5 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/helloworld.py @@ -0,0 +1,6 @@ +import sys + +while True: + line = sys.stdin.readline() + print('this is send from python') + print(line) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/install.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/install.py new file mode 100644 index 000000000..470d38321 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/install.py @@ -0,0 +1,23 @@ +import os +import subprocess + +def python3_version(): + return subprocess.check_call(["python3", "--version"]) + +def which(command): + return subprocess.check_call(["which", command]) + +def pip3_install_requirements(): + return subprocess.check_call(["pip3", "install", "-r", "requirements.txt", + "--user"]) + +def pip3_install_kfp(): + return subprocess.check_call(["pip3", "install", + "git+https://github.com/kubeflow/pipelines.git@1.8.19#subdirectory=backend/api/python_http_client", + "--user"]) + +python3_version() +pip3_install_requirements() +pip3_install_kfp() + +print("done") diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py new file mode 100644 index 000000000..da7ef822f --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_example.py @@ -0,0 +1,44 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +from kfp_server_api.rest import ApiException + +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "http://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +print("available namespace: {}".format(namespaces)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the API class + api_instance = kfp_server_api.ExperimentServiceApi(api_client) + resource_reference_key_type = "NAMESPACE" + resource_reference_key_id = namespaces[0] + list_experiment_response = api_instance.list_experiment(resource_reference_key_type=resource_reference_key_type, resource_reference_key_id=resource_reference_key_id) + for experiment in list_experiment_response.experiments: + print(experiment) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py new file mode 100644 index 000000000..7c95abcf0 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_login.py @@ -0,0 +1,93 @@ +import re +from urllib.parse import urlsplit + +import requests + +# NOTE: the following code is referred from https://github.com/kubeflow/website/issues/2916 +def get_istio_auth_session(url: str, username: str, password: str) -> dict: + """ + Determine if the specified URL is secured by Dex and try to obtain a session cookie. + WARNING: only Dex `staticPasswords` and `LDAP` authentication are currently supported + (we default default to using `staticPasswords` if both are enabled) + + :param url: Kubeflow server URL, including protocol + :param username: Dex `staticPasswords` or `LDAP` username + :param password: Dex `staticPasswords` or `LDAP` password + :return: auth session information + """ + # define the default return object + auth_session = { + "endpoint_url": url, # KF endpoint URL + "redirect_url": None, # KF redirect URL, if applicable + "dex_login_url": None, # Dex login URL (for POST of credentials) + "is_secured": None, # True if KF endpoint is secured + "session_cookie": None # Resulting session cookies in the form "key1=value1; key2=value2" + } + + # use a persistent session (for cookies) + with requests.Session() as s: + + ################ + # Determine if Endpoint is Secured + ################ + resp = s.get(url, allow_redirects=True) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {url}" + ) + + auth_session["redirect_url"] = resp.url + + # if we were NOT redirected, then the endpoint is UNSECURED + if len(resp.history) == 0: + auth_session["is_secured"] = False + return auth_session + else: + auth_session["is_secured"] = True + + ################ + # Get Dex Login URL + ################ + redirect_url_obj = urlsplit(auth_session["redirect_url"]) + + # if we are at `/auth?=xxxx` path, we need to select an auth type + if re.search(r"/auth$", redirect_url_obj.path): + # default to "staticPasswords" auth type + redirect_url_obj = redirect_url_obj._replace( + path=re.sub(r"/auth$", "/auth/local", redirect_url_obj.path) + ) + + # if we are at `/auth/xxxx/login` path, then no further action is needed (we can use it for login POST) + if re.search(r"/auth/.*/login$", redirect_url_obj.path): + auth_session["dex_login_url"] = redirect_url_obj.geturl() + + # else, we need to be redirected to the actual login page + else: + # this GET should redirect us to the `/auth/xxxx/login` path + resp = s.get(redirect_url_obj.geturl(), allow_redirects=True) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {redirect_url_obj.geturl()}" + ) + + # set the login url + auth_session["dex_login_url"] = resp.url + + ################ + # Attempt Dex Login + ################ + resp = s.post( + auth_session["dex_login_url"], + data={"login": username, "password": password}, + allow_redirects=True + ) + if len(resp.history) == 0: + raise RuntimeError( + f"Login credentials were probably invalid - " + f"No redirect after POST to: {auth_session['dex_login_url']}" + ) + + # store the session cookies in a "key1=value1; key2=value2" string + auth_session["session_cookie"] = "; ".join([f"{c.name}={c.value}" for c in s.cookies]) + + return auth_session \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py new file mode 100644 index 000000000..3c7c0dfdc --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/kfp_namespace.py @@ -0,0 +1,19 @@ +import os +import requests + +from typing import TypedDict + +def retrieve_namespaces(host: str, auth_session: TypedDict) -> str: + workgroup_endpoint = os.path.join(host, "api/workgroup/env-info") + + cookies = {} + cookie_tokens = auth_session["session_cookie"].split("=") + print(cookie_tokens[0]) + cookies[cookie_tokens[0]]=cookie_tokens[1] + resp = requests.get(workgroup_endpoint, cookies=cookies) + if resp.status_code != 200: + raise RuntimeError( + f"HTTP status code '{resp.status_code}' for GET against: {workgroup_endpoint}" + ) + return [ns["namespace"] for ns in resp.json()["namespaces"] if + ns["role"]=="owner"] \ No newline at end of file diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/mnist.py b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/mnist.py new file mode 100644 index 000000000..fc2911a05 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/mnist.py @@ -0,0 +1,132 @@ +from __future__ import print_function + +import time +import kfp_server_api +import os +import requests +import string +import random +import json +from kfp_server_api.rest import ApiException +from pprint import pprint +from kfp_login import get_istio_auth_session +from kfp_namespace import retrieve_namespaces + +host = "https://ai4edu.thu01.footprint-ai.com" +username = "thu02" +password = "M*$3sNF7" + +auth_session = get_istio_auth_session( + url=host, + username=username, + password=password + ) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Configure API key authorization: Bearer +configuration = kfp_server_api.Configuration( + host = os.path.join(host, "pipeline"), +) +configuration.debug = True + +namespaces = retrieve_namespaces(host, auth_session) +#print("available namespace: {}".format(namespaces)) + +def random_suffix() -> string: + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + +# Enter a context with an instance of the API client +with kfp_server_api.ApiClient(configuration, cookie=auth_session["session_cookie"]) as api_client: + # Create an instance of the Experiment API class + experiment_api_instance = kfp_server_api.ExperimentServiceApi(api_client) + name="experiment-" + random_suffix() + description="This is a experiment for mnist." + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey( + type=kfp_server_api.models.ApiResourceType.NAMESPACE, + id=resource_reference_key_id + ), + relationship=kfp_server_api.models.ApiRelationship.OWNER + )] + body = kfp_server_api.ApiExperiment(name=name, description=description, resource_references=resource_references) # ApiExperiment | The experiment to be created. + try: + # Creates a new experiment. + experiment_api_response = experiment_api_instance.create_experiment(body) + experiment_id = experiment_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling ExperimentServiceApi->create_experiment: %s\n" % e) + + # Create an instance of the pipeline API class + api_instance = kfp_server_api.PipelineUploadServiceApi(api_client) + uploadfile='pipelines/mnist_pipeline.yaml' + name='pipeline-' + random_suffix() + description="This is a mnist pipline." + try: + pipeline_api_response = api_instance.upload_pipeline(uploadfile, name=name, description=description) + pipeline_id = pipeline_api_response.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling PipelineUploadServiceApi->upload_pipeline: %s\n" % e) + + # Create an instance of the run API class + run_api_instance = kfp_server_api.RunServiceApi(api_client) + display_name = 'mnist' + random_suffix() + description = "This is a mnist run." + pipeline_spec = kfp_server_api.ApiPipelineSpec(pipeline_id=pipeline_id) + resource_reference_key_id = namespaces[0] + resource_references=[kfp_server_api.models.ApiResourceReference( + key=kfp_server_api.models.ApiResourceKey(id=experiment_id, type=kfp_server_api.models.ApiResourceType.EXPERIMENT), + relationship=kfp_server_api.models.ApiRelationship.OWNER )] + body = kfp_server_api.ApiRun(name=display_name, description=description, pipeline_spec=pipeline_spec, resource_references=resource_references) # ApiRun | + try: + # Creates a new run. + run_api_response = run_api_instance.create_run(body) + run_id = run_api_response.run.id # str | The ID of the run to be retrieved. + except ApiException as e: + print("Exception when calling RunServiceApi->create_run: %s\n" % e) + + Completed_flag = False + polling_interval = 10 # Time in seconds between polls + + while not Completed_flag: + try: + time.sleep(1) + # Finds a specific run by ID. + api_instance = run_api_instance.get_run(run_id) + output = api_instance.pipeline_runtime.workflow_manifest + output = json.loads(output) + + try: + nodes = output['status']['nodes'] + conditions = output['status']['conditions'] # Comfirm completion. + + except KeyError: + nodes = {} + conditions = [] + + output_value = None + Completed_flag = conditions[1]['status'] if len(conditions) > 1 else False + + except ApiException as e: + print("Exception when calling RunServiceApi->get_run: %s\n" % e) + break + + if not Completed_flag: + print("Pipeline is still running. Waiting...") + time.sleep(polling_interval-1) + + for node_id, node in nodes.items(): + if 'inputs' in node and 'parameters' in node['inputs']: + for parameter in node['inputs']['parameters']: + if parameter['name'] == 'client-last_accuracy': + output_value = parameter['value'] + + if output_value is not None: + print(f"fl Accuracy: {output_value}") + else: + print("Parameter not found.") + print(nodes) diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml new file mode 100644 index 000000000..11f53462f --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/LSTM_pipeline.yaml @@ -0,0 +1,651 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: fl-test- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2024-01-02T05:53:41.650368', + pipelines.kubeflow.org/pipeline_spec: '{"inputs": [{"default": "kubeflow-user-thu01", + "name": "namespace", "optional": true}], "name": "FL test"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} +spec: + entrypoint: fl-test + templates: + - name: client + container: + args: [--batch, '1', '----output-paths', /tmp/outputs/last_accuracy/data] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def client(batch):\n import json\n import requests\n import time\n\ + \ import pandas as pd\n import numpy as np\n import tensorflow as\ + \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ + \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ + \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ + \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ + \ tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import\ + \ Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras\ + \ import backend as K\n\n normal_url='https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'\ + \ \n abnormal_url='https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download'\n\ + \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ + \ num_features = len(normal_data.columns)\n print(num_features)\n \ + \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ + \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ + \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ + \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ + \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ + \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ + \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ + \n input_shape = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n\ + \ @staticmethod\n def build(shape, classes):\n model\ + \ = Sequential()\n model.add(LSTM(units=64, input_shape=input_shape,\ + \ return_sequences=True))\n model.add(Dropout(0.2))\n \ + \ model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n \ + \ model.add(Dense(units=num_classes, activation='softmax'))\n\n \ + \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ + \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ + \ #The client should have its own data, not like this. It's a lazy method.\n\ + \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ + \n #seperate shard into data and labels lists\n data, label\ + \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ + \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ + \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ + \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ + \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ + \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ + \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ + \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ + \ \n optimizer=optimizer, \n metrics=metrics)\n\ + \n if(comm_round == 0):\n history = client_model.fit(dataset,\ + \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ + \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ + \ test_loss, test_accuracy = client_model.evaluate(dataset)\n \ + \ print(f'Test accuracy: {test_accuracy}')\n\n local_weight = client_model.get_weights()\n\ + \ local_weight = [np.array(w).tolist() for w in local_weight]\n\n \ + \ client_data = {\"local_count\": local_count,'bs': bs, 'local_weight':\ + \ json.dumps(local_weight)}\n\n while True:\n try:\n \ + \ weight = (requests.post(server_url,data=client_data))\n\n \ + \ if weight.status_code == 200:\n print(f\"\ + exist\")\n\n break\n else:\n \ + \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ + \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ + \ data = weight.json()\n avg_weight = data.get('result')\n \ + \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ + \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ + \ \n try:\n response = requests.get(shutdown_url)\n except\ + \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ + \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ + \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ + \ str:\n if isinstance(float_value, str):\n return float_value\n\ + \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ + \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ + \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ + _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ + --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ + _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ + \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ + _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ + \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + outputs: + parameters: + - name: client-last_accuracy + valueFrom: {path: /tmp/outputs/last_accuracy/data} + artifacts: + - {name: client-last_accuracy, path: /tmp/outputs/last_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": + "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 + python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' + || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def client(batch):\n import json\n import requests\n import time\n import + pandas as pd\n import numpy as np\n import tensorflow as tf\n from + tensorflow.keras.models import Sequential\n from tensorflow.keras.layers + import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from + tensorflow.keras.layers import Activation\n from tensorflow.keras.layers + import Flatten\n from tensorflow.keras.layers import Dense\n from + tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import + Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras + import backend as K\n\n normal_url=''https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'' + \n abnormal_url=''https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download''\n normal_data + = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features + = len(normal_data.columns)\n print(num_features)\n normal_label = + np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, + 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label + = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data + = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), + num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data + = list(zip(data, data_label))\n data_length=len(full_data)\n\n input_shape + = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n @staticmethod\n def + build(shape, classes):\n model = Sequential()\n model.add(LSTM(units=64, + input_shape=input_shape, return_sequences=True))\n model.add(Dropout(0.2))\n model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n model.add(Dense(units=num_classes, + activation=''softmax''))\n\n return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] + #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] + #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data + len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate + shard into data and labels lists\n data, label = zip(*data_shard)\n dataset + = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return + dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs + = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics + = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for + comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model + = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, + \n metrics=metrics)\n\n if(comm_round == 0):\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n\n test_loss, test_accuracy + = client_model.evaluate(dataset)\n print(f''Test accuracy: {test_accuracy}'')\n\n local_weight + = client_model.get_weights()\n local_weight = [np.array(w).tolist() + for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': + bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight + = (requests.post(server_url,data=client_data))\n\n if weight.status_code + == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server + error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not + exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight + = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight + = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response + = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already + shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef + _serialize_float(float_value: float) -> str:\n if isinstance(float_value, + str):\n return float_value\n if not isinstance(float_value, (float, + int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + float.''.format(\n str(float_value), str(type(float_value))))\n return + str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', + description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, + required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": + "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": + "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": + "1"}'} + - name: client-2 + container: + args: [--batch, '2', '----output-paths', /tmp/outputs/last_accuracy/data] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def client(batch):\n import json\n import requests\n import time\n\ + \ import pandas as pd\n import numpy as np\n import tensorflow as\ + \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ + \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ + \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ + \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ + \ tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import\ + \ Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras\ + \ import backend as K\n\n normal_url='https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'\ + \ \n abnormal_url='https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download'\n\ + \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ + \ num_features = len(normal_data.columns)\n print(num_features)\n \ + \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ + \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ + \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ + \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ + \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ + \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ + \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ + \n input_shape = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n\ + \ @staticmethod\n def build(shape, classes):\n model\ + \ = Sequential()\n model.add(LSTM(units=64, input_shape=input_shape,\ + \ return_sequences=True))\n model.add(Dropout(0.2))\n \ + \ model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n \ + \ model.add(Dense(units=num_classes, activation='softmax'))\n\n \ + \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ + \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ + \ #The client should have its own data, not like this. It's a lazy method.\n\ + \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ + \n #seperate shard into data and labels lists\n data, label\ + \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ + \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ + \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ + \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ + \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ + \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ + \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ + \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ + \ \n optimizer=optimizer, \n metrics=metrics)\n\ + \n if(comm_round == 0):\n history = client_model.fit(dataset,\ + \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ + \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ + \ test_loss, test_accuracy = client_model.evaluate(dataset)\n \ + \ print(f'Test accuracy: {test_accuracy}')\n\n local_weight = client_model.get_weights()\n\ + \ local_weight = [np.array(w).tolist() for w in local_weight]\n\n \ + \ client_data = {\"local_count\": local_count,'bs': bs, 'local_weight':\ + \ json.dumps(local_weight)}\n\n while True:\n try:\n \ + \ weight = (requests.post(server_url,data=client_data))\n\n \ + \ if weight.status_code == 200:\n print(f\"\ + exist\")\n\n break\n else:\n \ + \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ + \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ + \ data = weight.json()\n avg_weight = data.get('result')\n \ + \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ + \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ + \ \n try:\n response = requests.get(shutdown_url)\n except\ + \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ + \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ + \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ + \ str:\n if isinstance(float_value, str):\n return float_value\n\ + \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ + \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ + \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ + _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ + --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ + _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ + \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ + _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ + \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + outputs: + artifacts: + - {name: client-2-last_accuracy, path: /tmp/outputs/last_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": + "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 + python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' + || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def client(batch):\n import json\n import requests\n import time\n import + pandas as pd\n import numpy as np\n import tensorflow as tf\n from + tensorflow.keras.models import Sequential\n from tensorflow.keras.layers + import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from + tensorflow.keras.layers import Activation\n from tensorflow.keras.layers + import Flatten\n from tensorflow.keras.layers import Dense\n from + tensorflow.keras.layers import LSTM\n from tensorflow.keras.layers import + Dropout\n from tensorflow.keras.optimizers import SGD\n from tensorflow.keras + import backend as K\n\n normal_url=''https://drive.google.com/uc?id=16SaNuh7P_UTIMKLX-7umTnDe27uKYRsK&export=download'' + \n abnormal_url=''https://drive.google.com/uc?id=1INzlvIOGcLAgXwSL-0ktN6hhy--gjtwp&export=download''\n normal_data + = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features + = len(normal_data.columns)\n print(num_features)\n normal_label = + np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, + 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label + = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data + = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), + num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data + = list(zip(data, data_label))\n data_length=len(full_data)\n\n input_shape + = (17, 1)\n num_classes = 2\n\n class SimpleMLP:\n @staticmethod\n def + build(shape, classes):\n model = Sequential()\n model.add(LSTM(units=64, + input_shape=input_shape, return_sequences=True))\n model.add(Dropout(0.2))\n model.add(LSTM(units=64))\n model.add(Dropout(0.2))\n model.add(Dense(units=num_classes, + activation=''softmax''))\n\n return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] + #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] + #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data + len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate + shard into data and labels lists\n data, label = zip(*data_shard)\n dataset + = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return + dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs + = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics + = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for + comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model + = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, + \n metrics=metrics)\n\n if(comm_round == 0):\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n\n test_loss, test_accuracy + = client_model.evaluate(dataset)\n print(f''Test accuracy: {test_accuracy}'')\n\n local_weight + = client_model.get_weights()\n local_weight = [np.array(w).tolist() + for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': + bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight + = (requests.post(server_url,data=client_data))\n\n if weight.status_code + == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server + error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not + exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight + = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight + = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response + = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already + shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef + _serialize_float(float_value: float) -> str:\n if isinstance(float_value, + str):\n return float_value\n if not isinstance(float_value, (float, + int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + float.''.format(\n str(float_value), str(type(float_value))))\n return + str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', + description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, + required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": + "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": + "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": + "2"}'} + - name: delete-service + resource: + action: delete + flags: [--wait=false] + manifest: | + apiVersion: v1 + kind: Service + metadata: + name: http-service + spec: + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + selector: + app: http-service + type: NodePort + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: fl-test + dag: + tasks: + - {name: client, template: client} + - {name: client-2, template: client-2} + - name: delete-service + template: delete-service + dependencies: [server] + - {name: http-service, template: http-service} + - name: server + template: server + dependencies: [http-service] + - name: show-results + template: show-results + dependencies: [client] + arguments: + parameters: + - {name: client-last_accuracy, value: '{{tasks.client.outputs.parameters.client-last_accuracy}}'} + - name: http-service + resource: + action: create + manifest: | + apiVersion: v1 + kind: Service + metadata: + name: http-service + spec: + ports: + - port: 5000 + protocol: TCP + targetPort: 8080 + selector: + app: http-service + outputs: + parameters: + - name: http-service-manifest + valueFrom: {jsonPath: '{}'} + - name: http-service-name + valueFrom: {jsonPath: '{.metadata.name}'} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: server + container: + args: [] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'flask' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'flask' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def server():\n import json\n import pandas as pd\n import numpy\ + \ as np\n import pickle\n import threading\n import time\n import\ + \ tensorflow as tf\n from flask import Flask, jsonify,request\n import\ + \ os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list\ + \ = []\n global_value = { #Share variable\n 'last_run_statue'\ + \ : False, #last run finish or not\n 'data_statue' : None,\ + \ #global_count finish or not\n 'global_count' : None,\n\ + \ 'scale_statue' : None,\n 'weight_statue'\ + \ : None,\n 'average_weights' : None,\n \ + \ 'shutdown' : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n \ + \ init_lock = threading.Lock()\n clients_local_count_lock = threading.Lock()\n\ + \ scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock\ + \ = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n\ + \ def before_request():\n print('get request')\n\n @app.route('/data',\ + \ methods=['POST'])\n def flask_server():\n with init_lock: #check\ + \ last run is finish and init varible\n\n while True:\n\n \ + \ if(len(clients_local_count)==0 and global_value['last_run_statue']\ + \ == False):#init the variable by first client enter\n \ + \ global_value['last_run_statue'] = True\n global_value['data_statue']\ + \ = False\n global_value['scale_statue'] = False\n \ + \ global_value['weight_statue'] = False\n \ + \ break\n\n elif(global_value['last_run_statue'] == True):\n\ + \ break\n time.sleep(3)\n\n local_count\ + \ = int(request.form.get('local_count')) #get data\n bs =\ + \ int(request.form.get('bs'))\n local_weight = json.loads(request.form.get('local_weight'))\n\ + \ local_weight = [np.array(lst) for lst in local_weight]\n\n \ + \ def scale_model_weights(weight, scalar):\n weight_final = []\n\ + \ steps = len(weight)\n for i in range(steps):\n \ + \ weight_final.append(scalar * weight[i])\n return\ + \ weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n \ + \ avg_grad = list()\n #get the average grad accross all\ + \ client gradients\n for grad_list_tuple in zip(*scaled_weight_list):\n\ + \ layer_mean = tf.math.reduce_sum(grad_list_tuple, axis=0)\n\ + \ avg_grad.append(layer_mean)\n\n return avg_grad\n\ + \n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\ + \n with scaled_local_weight_list_lock:\n while True:\n\n\ + \ if (len(clients_local_count) == NUM_OF_CLIENTS and global_value['data_statue']\ + \ != True):\n global_value['last_run_statue'] = False\n\ + \ sum_of_local_count=sum(clients_local_count)\n\n \ + \ global_value['global_count'] = sum_of_local_count \n\n\ + \ scaling_factor=local_count/global_value['global_count']\n\ + \ scaled_weights = scale_model_weights(local_weight, scaling_factor)\n\ + \ scaled_local_weight_list.append(scaled_weights)\n\n \ + \ global_value['scale_statue'] = True \n \ + \ global_value['data_statue'] = True\n break\n \ + \ elif (global_value['data_statue'] == True and global_value['scale_statue']\ + \ == True):\n scaling_factor=local_count/global_value['global_count']\n\ + \ scaled_weights =scale_model_weights(local_weight, scaling_factor)\n\ + \ scaled_local_weight_list.append(scaled_weights)\n\n \ + \ break\n time.sleep(1)\n\n with cal_weight_lock:\n\ + \n while True:\n if(len(scaled_local_weight_list)\ + \ == NUM_OF_CLIENTS and global_value['weight_statue'] != True):\n\n \ + \ global_value['average_weights'] = sum_scaled_weights(scaled_local_weight_list)\n\ + \ global_value['weight_statue'] = True\n \ + \ global_value['average_weights'] = json.dumps([np.array(w).tolist()\ + \ for w in global_value['average_weights']])\n\n break\n\ + \n elif(global_value['weight_statue'] == True):\n\n \ + \ break\n\n time.sleep(1)\n\n clients_local_count.clear()\n\ + \ scaled_local_weight_list.clear()\n\n return jsonify({'result':\ + \ (global_value['average_weights'])})\n\n @app.route('/shutdown', methods=['GET'])\n\ + \ def shutdown_server():\n global_value['shutdown'] +=1 \n \ + \ with shutdown_lock:\n while True:\n if(global_value['shutdown']\ + \ == NUM_OF_CLIENTS):\n os._exit(0)\n \ + \ return 'Server shutting down...'\n time.sleep(1)\n\n \ + \ app.run(host=\"0.0.0.0\", port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Server',\ + \ description='')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs =\ + \ server(**_parsed_args)\n" + image: tensorflow/tensorflow + ports: + - {containerPort: 8080, name: my-port} + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + metadata: + labels: + app: http-service + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": [], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 python3 + -m pip install --quiet --no-warn-script-location ''flask'' ''pandas'' || + PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''flask'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def server():\n import json\n import pandas as pd\n import numpy + as np\n import pickle\n import threading\n import time\n import + tensorflow as tf\n from flask import Flask, jsonify,request\n import + os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list + = []\n global_value = { #Share variable\n ''last_run_statue'' + : False, #last run finish or not\n ''data_statue'' : + None, #global_count finish or not\n ''global_count'' + : None,\n ''scale_statue'' : None,\n ''weight_statue'' + : None,\n ''average_weights'' : None,\n ''shutdown'' + : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n init_lock = threading.Lock()\n clients_local_count_lock + = threading.Lock()\n scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock + = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n def + before_request():\n print(''get request'')\n\n @app.route(''/data'', + methods=[''POST''])\n def flask_server():\n with init_lock: #check + last run is finish and init varible\n\n while True:\n\n if(len(clients_local_count)==0 + and global_value[''last_run_statue''] == False):#init the variable by first + client enter\n global_value[''last_run_statue''] = True\n global_value[''data_statue''] + = False\n global_value[''scale_statue''] = False\n global_value[''weight_statue''] + = False\n break\n\n elif(global_value[''last_run_statue''] + == True):\n break\n time.sleep(3)\n\n local_count + = int(request.form.get(''local_count'')) #get data\n bs + = int(request.form.get(''bs''))\n local_weight = json.loads(request.form.get(''local_weight''))\n local_weight + = [np.array(lst) for lst in local_weight]\n\n def scale_model_weights(weight, + scalar):\n weight_final = []\n steps = len(weight)\n for + i in range(steps):\n weight_final.append(scalar * weight[i])\n return + weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n avg_grad + = list()\n #get the average grad accross all client gradients\n for + grad_list_tuple in zip(*scaled_weight_list):\n layer_mean + = tf.math.reduce_sum(grad_list_tuple, axis=0)\n avg_grad.append(layer_mean)\n\n return + avg_grad\n\n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\n with + scaled_local_weight_list_lock:\n while True:\n\n if + (len(clients_local_count) == NUM_OF_CLIENTS and global_value[''data_statue''] + != True):\n global_value[''last_run_statue''] = False\n sum_of_local_count=sum(clients_local_count)\n\n global_value[''global_count''] + = sum_of_local_count \n\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights + = scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n global_value[''scale_statue''] + = True \n global_value[''data_statue''] = True\n break\n elif + (global_value[''data_statue''] == True and global_value[''scale_statue''] + == True):\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights + =scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n break\n time.sleep(1)\n\n with + cal_weight_lock:\n\n while True:\n if(len(scaled_local_weight_list) + == NUM_OF_CLIENTS and global_value[''weight_statue''] != True):\n\n global_value[''average_weights''] + = sum_scaled_weights(scaled_local_weight_list)\n global_value[''weight_statue''] + = True\n global_value[''average_weights''] = json.dumps([np.array(w).tolist() + for w in global_value[''average_weights'']])\n\n break\n\n elif(global_value[''weight_statue''] + == True):\n\n break\n\n time.sleep(1)\n\n clients_local_count.clear()\n scaled_local_weight_list.clear()\n\n return + jsonify({''result'': (global_value[''average_weights''])})\n\n @app.route(''/shutdown'', + methods=[''GET''])\n def shutdown_server():\n global_value[''shutdown''] + +=1 \n with shutdown_lock:\n while True:\n if(global_value[''shutdown''] + == NUM_OF_CLIENTS):\n os._exit(0)\n return + ''Server shutting down...''\n time.sleep(1)\n\n app.run(host=\"0.0.0.0\", + port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Server'', + description='''')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs + = server(**_parsed_args)\n"], "image": "tensorflow/tensorflow"}}, "name": + "Server"}', pipelines.kubeflow.org/component_ref: '{}'} + - name: show-results + container: + args: [--test-acc, '{{inputs.parameters.client-last_accuracy}}', '----output-paths', + /tmp/outputs/test_accuracy/data] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - | + def show_results(test_acc): + return([test_acc]) + + def _serialize_float(float_value: float) -> str: + if isinstance(float_value, str): + return float_value + if not isinstance(float_value, (float, int)): + raise TypeError('Value "{}" has type "{}" instead of float.'.format( + str(float_value), str(type(float_value)))) + return str(float_value) + + import argparse + _parser = argparse.ArgumentParser(prog='Show results', description='') + _parser.add_argument("--test-acc", dest="test_acc", type=float, required=True, default=argparse.SUPPRESS) + _parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=1) + _parsed_args = vars(_parser.parse_args()) + _output_files = _parsed_args.pop("_output_paths", []) + + _outputs = show_results(**_parsed_args) + + _output_serializers = [ + _serialize_float, + + ] + + import os + for idx, output_file in enumerate(_output_files): + try: + os.makedirs(os.path.dirname(output_file)) + except OSError: + pass + with open(output_file, 'w') as f: + f.write(_output_serializers[idx](_outputs[idx])) + image: python:3.7 + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + inputs: + parameters: + - {name: client-last_accuracy} + outputs: + artifacts: + - {name: show-results-test_accuracy, path: /tmp/outputs/test_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--test-acc", {"inputValue": "test_acc"}, "----output-paths", + {"outputPath": "test_accuracy"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def show_results(test_acc):\n return([test_acc])\n\ndef _serialize_float(float_value: + float) -> str:\n if isinstance(float_value, str):\n return float_value\n if + not isinstance(float_value, (float, int)):\n raise TypeError(''Value + \"{}\" has type \"{}\" instead of float.''.format(\n str(float_value), + str(type(float_value))))\n return str(float_value)\n\nimport argparse\n_parser + = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--test-acc\", + dest=\"test_acc\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = show_results(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "python:3.7"}}, "inputs": [{"name": "test_acc", "type": "Float"}], + "name": "Show results", "outputs": [{"name": "test_accuracy", "type": "Float"}]}', + pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"test_acc": + "{{inputs.parameters.client-last_accuracy}}"}'} + arguments: + parameters: + - {name: namespace, value: kubeflow-user-thu01} + serviceAccountName: pipeline-runner diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml new file mode 100644 index 000000000..8381600f3 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/fl_pipeline.yaml @@ -0,0 +1,639 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: fl-test- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-12-13T03:33:40.267552', + pipelines.kubeflow.org/pipeline_spec: '{"inputs": [{"default": "kubeflow-user-thu01", + "name": "namespace", "optional": true}], "name": "FL test"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} +spec: + entrypoint: fl-test + templates: + - name: client + container: + args: [--batch, '1', '----output-paths', /tmp/outputs/last_accuracy/data] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def client(batch):\n import json\n import requests\n import time\n\ + \ import pandas as pd\n import numpy as np\n import tensorflow as\ + \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ + \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ + \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ + \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ + \ tensorflow.keras.optimizers import SGD\n from tensorflow.keras import\ + \ backend as K\n\n normal_url='https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'\ + \ \n abnormal_url='https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy'\n\ + \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ + \ num_features = len(normal_data.columns)\n print(num_features)\n \ + \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ + \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ + \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ + \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ + \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ + \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ + \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ + \n class SimpleMLP:\n @staticmethod\n def build(shape, classes):\n\ + \ model = Sequential()\n model.add(Conv1D(filters=4,\ + \ kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n\ + \ model.add(Flatten())\n model.add(Dense(8, activation=\"\ + relu\"))\n model.add(Dense(2, activation = 'softmax'))\n\n \ + \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ + \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ + \ #The client should have its own data, not like this. It's a lazy method.\n\ + \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ + \n #seperate shard into data and labels lists\n data, label\ + \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ + \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ + \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ + \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ + \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ + \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ + \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ + \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ + \ \n optimizer=optimizer, \n metrics=metrics)\n\ + \n if(comm_round == 0):\n history = client_model.fit(dataset,\ + \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ + \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ + \ local_weight = client_model.get_weights()\n local_weight =\ + \ [np.array(w).tolist() for w in local_weight]\n\n client_data = {\"\ + local_count\": local_count,'bs': bs, 'local_weight': json.dumps(local_weight)}\n\ + \n while True:\n try:\n weight = (requests.post(server_url,data=client_data))\n\ + \n if weight.status_code == 200:\n print(f\"\ + exist\")\n\n break\n else:\n \ + \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ + \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ + \ data = weight.json()\n avg_weight = data.get('result')\n \ + \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ + \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ + \ \n try:\n response = requests.get(shutdown_url)\n except\ + \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ + \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ + \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ + \ str:\n if isinstance(float_value, str):\n return float_value\n\ + \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ + \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ + \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ + _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ + --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ + _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ + \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ + _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ + \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + outputs: + parameters: + - name: client-last_accuracy + valueFrom: {path: /tmp/outputs/last_accuracy/data} + artifacts: + - {name: client-last_accuracy, path: /tmp/outputs/last_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": + "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 + python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' + || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def client(batch):\n import json\n import requests\n import time\n import + pandas as pd\n import numpy as np\n import tensorflow as tf\n from + tensorflow.keras.models import Sequential\n from tensorflow.keras.layers + import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from + tensorflow.keras.layers import Activation\n from tensorflow.keras.layers + import Flatten\n from tensorflow.keras.layers import Dense\n from + tensorflow.keras.optimizers import SGD\n from tensorflow.keras import + backend as K\n\n normal_url=''https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'' + \n abnormal_url=''https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy''\n normal_data + = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features + = len(normal_data.columns)\n print(num_features)\n normal_label = + np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, + 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label + = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data + = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), + num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data + = list(zip(data, data_label))\n data_length=len(full_data)\n\n class + SimpleMLP:\n @staticmethod\n def build(shape, classes):\n model + = Sequential()\n model.add(Conv1D(filters=4, kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n model.add(Flatten())\n model.add(Dense(8, + activation=\"relu\"))\n model.add(Dense(2, activation = ''softmax''))\n\n return + model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] + #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] + #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data + len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate + shard into data and labels lists\n data, label = zip(*data_shard)\n dataset + = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return + dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs + = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics + = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for + comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model + = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, + \n metrics=metrics)\n\n if(comm_round == 0):\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n\n local_weight + = client_model.get_weights()\n local_weight = [np.array(w).tolist() + for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': + bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight + = (requests.post(server_url,data=client_data))\n\n if weight.status_code + == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server + error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not + exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight + = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight + = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response + = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already + shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef + _serialize_float(float_value: float) -> str:\n if isinstance(float_value, + str):\n return float_value\n if not isinstance(float_value, (float, + int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + float.''.format(\n str(float_value), str(type(float_value))))\n return + str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', + description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, + required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": + "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": + "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": + "1"}'} + - name: client-2 + container: + args: [--batch, '2', '----output-paths', /tmp/outputs/last_accuracy/data] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'requests' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'requests' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def client(batch):\n import json\n import requests\n import time\n\ + \ import pandas as pd\n import numpy as np\n import tensorflow as\ + \ tf\n from tensorflow.keras.models import Sequential\n from tensorflow.keras.layers\ + \ import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n \ + \ from tensorflow.keras.layers import Activation\n from tensorflow.keras.layers\ + \ import Flatten\n from tensorflow.keras.layers import Dense\n from\ + \ tensorflow.keras.optimizers import SGD\n from tensorflow.keras import\ + \ backend as K\n\n normal_url='https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'\ + \ \n abnormal_url='https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy'\n\ + \ normal_data = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n\ + \ num_features = len(normal_data.columns)\n print(num_features)\n \ + \ normal_label = np.array([[1, 0]] * len(normal_data))\n abnormal_label\ + \ = np.array([[0, 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data,\ + \ abnormal_data))\n data_label = np.vstack((normal_label, abnormal_label))\n\ + \n shuffler = np.random.permutation(len(data))\n data = data[shuffler]\n\ + \ data_label = data_label[shuffler]\n\n data = data.reshape(len(data),\ + \ num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\ + \n full_data = list(zip(data, data_label))\n data_length=len(full_data)\n\ + \n class SimpleMLP:\n @staticmethod\n def build(shape, classes):\n\ + \ model = Sequential()\n model.add(Conv1D(filters=4,\ + \ kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n\ + \ model.add(Flatten())\n model.add(Dense(8, activation=\"\ + relu\"))\n model.add(Dense(2, activation = 'softmax'))\n\n \ + \ return model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)]\ + \ #batch data\n else:\n full_data=full_data[int(data_length/2):data_length]\ + \ #The client should have its own data, not like this. It's a lazy method.\n\ + \n print('data len= ',len(full_data))\n def batch_data(data_shard, bs=32):\n\ + \n #seperate shard into data and labels lists\n data, label\ + \ = zip(*data_shard)\n dataset = tf.data.Dataset.from_tensor_slices((list(data),\ + \ list(label)))\n return dataset.shuffle(len(label)).batch(bs)\n\n\ + \ dataset=batch_data(full_data)\n #print(dataset)\n\n bs = next(iter(dataset))[0].shape[0]\n\ + \ local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n\ + \ loss='categorical_crossentropy'\n metrics = ['accuracy']\n optimizer\ + \ = 'adam'\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\ + \n for comm_round in range(1):\n print('The ',comm_round+1, 'round')\n\ + \ client_model = smlp_model.build(17, 1)\n client_model.compile(loss=loss,\ + \ \n optimizer=optimizer, \n metrics=metrics)\n\ + \n if(comm_round == 0):\n history = client_model.fit(dataset,\ + \ epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n\ + \ history = client_model.fit(dataset, epochs=5, verbose=1)\n\n\ + \ local_weight = client_model.get_weights()\n local_weight =\ + \ [np.array(w).tolist() for w in local_weight]\n\n client_data = {\"\ + local_count\": local_count,'bs': bs, 'local_weight': json.dumps(local_weight)}\n\ + \n while True:\n try:\n weight = (requests.post(server_url,data=client_data))\n\ + \n if weight.status_code == 200:\n print(f\"\ + exist\")\n\n break\n else:\n \ + \ print(f\"server error\")\n\n except requests.exceptions.RequestException:\n\ + \n print(f\"not exist\")\n\n time.sleep(5)\n\n \ + \ data = weight.json()\n avg_weight = data.get('result')\n \ + \ avg_weight = json.loads(avg_weight)\n avg_weight = [np.array(lst)\ + \ for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\"\ + \ \n try:\n response = requests.get(shutdown_url)\n except\ + \ requests.exceptions.ConnectionError:\n print('already shutdown')\n\ + \ last_accuracy = history.history['accuracy'][-1]\n print(last_accuracy)\n\ + \ return([last_accuracy])\n\ndef _serialize_float(float_value: float) ->\ + \ str:\n if isinstance(float_value, str):\n return float_value\n\ + \ if not isinstance(float_value, (float, int)):\n raise TypeError('Value\ + \ \"{}\" has type \"{}\" instead of float.'.format(\n str(float_value),\ + \ str(type(float_value))))\n return str(float_value)\n\nimport argparse\n\ + _parser = argparse.ArgumentParser(prog='Client', description='')\n_parser.add_argument(\"\ + --batch\", dest=\"batch\", type=int, required=True, default=argparse.SUPPRESS)\n\ + _parser.add_argument(\"----output-paths\", dest=\"_output_paths\", type=str,\ + \ nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"\ + _output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers\ + \ = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + outputs: + artifacts: + - {name: client-2-last_accuracy, path: /tmp/outputs/last_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--batch", {"inputValue": "batch"}, "----output-paths", {"outputPath": + "last_accuracy"}], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 + python3 -m pip install --quiet --no-warn-script-location ''requests'' ''pandas'' + || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''requests'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def client(batch):\n import json\n import requests\n import time\n import + pandas as pd\n import numpy as np\n import tensorflow as tf\n from + tensorflow.keras.models import Sequential\n from tensorflow.keras.layers + import Conv1D\n from tensorflow.keras.layers import MaxPooling1D\n from + tensorflow.keras.layers import Activation\n from tensorflow.keras.layers + import Flatten\n from tensorflow.keras.layers import Dense\n from + tensorflow.keras.optimizers import SGD\n from tensorflow.keras import + backend as K\n\n normal_url=''https://drive.google.com/u/0/uc?id=1TQHKkP6yzuhcxw_JCtby9jQwY2AMLiNi&export=download'' + \n abnormal_url=''https://drive.google.com/uc?export=download&id=1i22tQI2vib0fsd1wwVP1tEydmGEksmpy''\n normal_data + = pd.read_csv(normal_url)\n abnormal_data = pd.read_csv(abnormal_url)\n num_features + = len(normal_data.columns)\n print(num_features)\n normal_label = + np.array([[1, 0]] * len(normal_data))\n abnormal_label = np.array([[0, + 1]] * len(abnormal_data))\n\n data = np.vstack((normal_data, abnormal_data))\n data_label + = np.vstack((normal_label, abnormal_label))\n\n shuffler = np.random.permutation(len(data))\n data + = data[shuffler]\n data_label = data_label[shuffler]\n\n data = data.reshape(len(data), + num_features, 1)\n data_label = data_label.reshape(len(data_label), 2)\n\n full_data + = list(zip(data, data_label))\n data_length=len(full_data)\n\n class + SimpleMLP:\n @staticmethod\n def build(shape, classes):\n model + = Sequential()\n model.add(Conv1D(filters=4, kernel_size=3, input_shape=(17,1)))\n model.add(MaxPooling1D(3))\n model.add(Flatten())\n model.add(Dense(8, + activation=\"relu\"))\n model.add(Dense(2, activation = ''softmax''))\n\n return + model\n\n if(batch==1):\n full_data=full_data[0:int(data_length/2)] + #batch data\n else:\n full_data=full_data[int(data_length/2):data_length] + #The client should have its own data, not like this. It''s a lazy method.\n\n print(''data + len= '',len(full_data))\n def batch_data(data_shard, bs=32):\n\n #seperate + shard into data and labels lists\n data, label = zip(*data_shard)\n dataset + = tf.data.Dataset.from_tensor_slices((list(data), list(label)))\n return + dataset.shuffle(len(label)).batch(bs)\n\n dataset=batch_data(full_data)\n #print(dataset)\n\n bs + = next(iter(dataset))[0].shape[0]\n local_count = tf.data.experimental.cardinality(dataset).numpy()*bs\n\n loss=''categorical_crossentropy''\n metrics + = [''accuracy'']\n optimizer = ''adam''\n\n smlp_model = SimpleMLP()\n\n server_url=\"http://http-service:5000/data\"\n for + comm_round in range(1):\n print(''The '',comm_round+1, ''round'')\n client_model + = smlp_model.build(17, 1)\n client_model.compile(loss=loss, \n optimizer=optimizer, + \n metrics=metrics)\n\n if(comm_round == 0):\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n else:\n client_model.set_weights(avg_weight)\n history + = client_model.fit(dataset, epochs=5, verbose=1)\n\n local_weight + = client_model.get_weights()\n local_weight = [np.array(w).tolist() + for w in local_weight]\n\n client_data = {\"local_count\": local_count,''bs'': + bs, ''local_weight'': json.dumps(local_weight)}\n\n while True:\n try:\n weight + = (requests.post(server_url,data=client_data))\n\n if weight.status_code + == 200:\n print(f\"exist\")\n\n break\n else:\n print(f\"server + error\")\n\n except requests.exceptions.RequestException:\n\n print(f\"not + exist\")\n\n time.sleep(5)\n\n data = weight.json()\n avg_weight + = data.get(''result'')\n avg_weight = json.loads(avg_weight)\n avg_weight + = [np.array(lst) for lst in avg_weight]\n\n shutdown_url=\"http://http-service:5000/shutdown\" \n try:\n response + = requests.get(shutdown_url)\n except requests.exceptions.ConnectionError:\n print(''already + shutdown'')\n last_accuracy = history.history[''accuracy''][-1]\n print(last_accuracy)\n return([last_accuracy])\n\ndef + _serialize_float(float_value: float) -> str:\n if isinstance(float_value, + str):\n return float_value\n if not isinstance(float_value, (float, + int)):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + float.''.format(\n str(float_value), str(type(float_value))))\n return + str(float_value)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Client'', + description='''')\n_parser.add_argument(\"--batch\", dest=\"batch\", type=int, + required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = client(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow"}}, "inputs": [{"name": "batch", "type": + "Integer"}], "name": "Client", "outputs": [{"name": "last_accuracy", "type": + "Float"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"batch": + "2"}'} + - name: delete-service + resource: + action: delete + flags: [--wait=false] + manifest: | + apiVersion: v1 + kind: Service + metadata: + name: http-service + spec: + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + selector: + app: http-service + type: NodePort + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: fl-test + dag: + tasks: + - {name: client, template: client} + - {name: client-2, template: client-2} + - name: delete-service + template: delete-service + dependencies: [server] + - {name: http-service, template: http-service} + - name: server + template: server + dependencies: [http-service] + - name: show-results + template: show-results + dependencies: [client] + arguments: + parameters: + - {name: client-last_accuracy, value: '{{tasks.client.outputs.parameters.client-last_accuracy}}'} + - name: http-service + resource: + action: create + manifest: | + apiVersion: v1 + kind: Service + metadata: + name: http-service + spec: + ports: + - port: 5000 + protocol: TCP + targetPort: 8080 + selector: + app: http-service + outputs: + parameters: + - name: http-service-manifest + valueFrom: {jsonPath: '{}'} + - name: http-service-name + valueFrom: {jsonPath: '{.metadata.name}'} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: server + container: + args: [] + command: + - sh + - -c + - (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + 'flask' 'pandas' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install + --quiet --no-warn-script-location 'flask' 'pandas' --user) && "$0" "$@" + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def server():\n import json\n import pandas as pd\n import numpy\ + \ as np\n import pickle\n import threading\n import time\n import\ + \ tensorflow as tf\n from flask import Flask, jsonify,request\n import\ + \ os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list\ + \ = []\n global_value = { #Share variable\n 'last_run_statue'\ + \ : False, #last run finish or not\n 'data_statue' : None,\ + \ #global_count finish or not\n 'global_count' : None,\n\ + \ 'scale_statue' : None,\n 'weight_statue'\ + \ : None,\n 'average_weights' : None,\n \ + \ 'shutdown' : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n \ + \ init_lock = threading.Lock()\n clients_local_count_lock = threading.Lock()\n\ + \ scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock\ + \ = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n\ + \ def before_request():\n print('get request')\n\n @app.route('/data',\ + \ methods=['POST'])\n def flask_server():\n with init_lock: #check\ + \ last run is finish and init varible\n\n while True:\n\n \ + \ if(len(clients_local_count)==0 and global_value['last_run_statue']\ + \ == False):#init the variable by first client enter\n \ + \ global_value['last_run_statue'] = True\n global_value['data_statue']\ + \ = False\n global_value['scale_statue'] = False\n \ + \ global_value['weight_statue'] = False\n \ + \ break\n\n elif(global_value['last_run_statue'] == True):\n\ + \ break\n time.sleep(3)\n\n local_count\ + \ = int(request.form.get('local_count')) #get data\n bs =\ + \ int(request.form.get('bs'))\n local_weight = json.loads(request.form.get('local_weight'))\n\ + \ local_weight = [np.array(lst) for lst in local_weight]\n\n \ + \ def scale_model_weights(weight, scalar):\n weight_final = []\n\ + \ steps = len(weight)\n for i in range(steps):\n \ + \ weight_final.append(scalar * weight[i])\n return\ + \ weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n \ + \ avg_grad = list()\n #get the average grad accross all\ + \ client gradients\n for grad_list_tuple in zip(*scaled_weight_list):\n\ + \ layer_mean = tf.math.reduce_sum(grad_list_tuple, axis=0)\n\ + \ avg_grad.append(layer_mean)\n\n return avg_grad\n\ + \n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\ + \n with scaled_local_weight_list_lock:\n while True:\n\n\ + \ if (len(clients_local_count) == NUM_OF_CLIENTS and global_value['data_statue']\ + \ != True):\n global_value['last_run_statue'] = False\n\ + \ sum_of_local_count=sum(clients_local_count)\n\n \ + \ global_value['global_count'] = sum_of_local_count \n\n\ + \ scaling_factor=local_count/global_value['global_count']\n\ + \ scaled_weights = scale_model_weights(local_weight, scaling_factor)\n\ + \ scaled_local_weight_list.append(scaled_weights)\n\n \ + \ global_value['scale_statue'] = True \n \ + \ global_value['data_statue'] = True\n break\n \ + \ elif (global_value['data_statue'] == True and global_value['scale_statue']\ + \ == True):\n scaling_factor=local_count/global_value['global_count']\n\ + \ scaled_weights =scale_model_weights(local_weight, scaling_factor)\n\ + \ scaled_local_weight_list.append(scaled_weights)\n\n \ + \ break\n time.sleep(1)\n\n with cal_weight_lock:\n\ + \n while True:\n if(len(scaled_local_weight_list)\ + \ == NUM_OF_CLIENTS and global_value['weight_statue'] != True):\n\n \ + \ global_value['average_weights'] = sum_scaled_weights(scaled_local_weight_list)\n\ + \ global_value['weight_statue'] = True\n \ + \ global_value['average_weights'] = json.dumps([np.array(w).tolist()\ + \ for w in global_value['average_weights']])\n\n break\n\ + \n elif(global_value['weight_statue'] == True):\n\n \ + \ break\n\n time.sleep(1)\n\n clients_local_count.clear()\n\ + \ scaled_local_weight_list.clear()\n\n return jsonify({'result':\ + \ (global_value['average_weights'])})\n\n @app.route('/shutdown', methods=['GET'])\n\ + \ def shutdown_server():\n global_value['shutdown'] +=1 \n \ + \ with shutdown_lock:\n while True:\n if(global_value['shutdown']\ + \ == NUM_OF_CLIENTS):\n os._exit(0)\n \ + \ return 'Server shutting down...'\n time.sleep(1)\n\n \ + \ app.run(host=\"0.0.0.0\", port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Server',\ + \ description='')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs =\ + \ server(**_parsed_args)\n" + image: tensorflow/tensorflow + ports: + - {containerPort: 8080, name: my-port} + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + metadata: + labels: + app: http-service + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": [], "command": ["sh", "-c", "(PIP_DISABLE_PIP_VERSION_CHECK=1 python3 + -m pip install --quiet --no-warn-script-location ''flask'' ''pandas'' || + PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location + ''flask'' ''pandas'' --user) && \"$0\" \"$@\"", "sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def server():\n import json\n import pandas as pd\n import numpy + as np\n import pickle\n import threading\n import time\n import + tensorflow as tf\n from flask import Flask, jsonify,request\n import + os\n\n app = Flask(__name__)\n clients_local_count = []\n scaled_local_weight_list + = []\n global_value = { #Share variable\n ''last_run_statue'' + : False, #last run finish or not\n ''data_statue'' : + None, #global_count finish or not\n ''global_count'' + : None,\n ''scale_statue'' : None,\n ''weight_statue'' + : None,\n ''average_weights'' : None,\n ''shutdown'' + : 0}\n\n NUM_OF_CLIENTS = 2 #number of clients\n\n init_lock = threading.Lock()\n clients_local_count_lock + = threading.Lock()\n scaled_local_weight_list_lock = threading.Lock()\n cal_weight_lock + = threading.Lock()\n shutdown_lock = threading.Lock()\n\n @app.before_request\n def + before_request():\n print(''get request'')\n\n @app.route(''/data'', + methods=[''POST''])\n def flask_server():\n with init_lock: #check + last run is finish and init varible\n\n while True:\n\n if(len(clients_local_count)==0 + and global_value[''last_run_statue''] == False):#init the variable by first + client enter\n global_value[''last_run_statue''] = True\n global_value[''data_statue''] + = False\n global_value[''scale_statue''] = False\n global_value[''weight_statue''] + = False\n break\n\n elif(global_value[''last_run_statue''] + == True):\n break\n time.sleep(3)\n\n local_count + = int(request.form.get(''local_count'')) #get data\n bs + = int(request.form.get(''bs''))\n local_weight = json.loads(request.form.get(''local_weight''))\n local_weight + = [np.array(lst) for lst in local_weight]\n\n def scale_model_weights(weight, + scalar):\n weight_final = []\n steps = len(weight)\n for + i in range(steps):\n weight_final.append(scalar * weight[i])\n return + weight_final\n def sum_scaled_weights(scaled_weight_list):\n\n avg_grad + = list()\n #get the average grad accross all client gradients\n for + grad_list_tuple in zip(*scaled_weight_list):\n layer_mean + = tf.math.reduce_sum(grad_list_tuple, axis=0)\n avg_grad.append(layer_mean)\n\n return + avg_grad\n\n with clients_local_count_lock:\n clients_local_count.append(int(local_count))\n\n with + scaled_local_weight_list_lock:\n while True:\n\n if + (len(clients_local_count) == NUM_OF_CLIENTS and global_value[''data_statue''] + != True):\n global_value[''last_run_statue''] = False\n sum_of_local_count=sum(clients_local_count)\n\n global_value[''global_count''] + = sum_of_local_count \n\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights + = scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n global_value[''scale_statue''] + = True \n global_value[''data_statue''] = True\n break\n elif + (global_value[''data_statue''] == True and global_value[''scale_statue''] + == True):\n scaling_factor=local_count/global_value[''global_count'']\n scaled_weights + =scale_model_weights(local_weight, scaling_factor)\n scaled_local_weight_list.append(scaled_weights)\n\n break\n time.sleep(1)\n\n with + cal_weight_lock:\n\n while True:\n if(len(scaled_local_weight_list) + == NUM_OF_CLIENTS and global_value[''weight_statue''] != True):\n\n global_value[''average_weights''] + = sum_scaled_weights(scaled_local_weight_list)\n global_value[''weight_statue''] + = True\n global_value[''average_weights''] = json.dumps([np.array(w).tolist() + for w in global_value[''average_weights'']])\n\n break\n\n elif(global_value[''weight_statue''] + == True):\n\n break\n\n time.sleep(1)\n\n clients_local_count.clear()\n scaled_local_weight_list.clear()\n\n return + jsonify({''result'': (global_value[''average_weights''])})\n\n @app.route(''/shutdown'', + methods=[''GET''])\n def shutdown_server():\n global_value[''shutdown''] + +=1 \n with shutdown_lock:\n while True:\n if(global_value[''shutdown''] + == NUM_OF_CLIENTS):\n os._exit(0)\n return + ''Server shutting down...''\n time.sleep(1)\n\n app.run(host=\"0.0.0.0\", + port=8080)\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Server'', + description='''')\n_parsed_args = vars(_parser.parse_args())\n\n_outputs + = server(**_parsed_args)\n"], "image": "tensorflow/tensorflow"}}, "name": + "Server"}', pipelines.kubeflow.org/component_ref: '{}'} + - name: show-results + container: + args: [--test-acc, '{{inputs.parameters.client-last_accuracy}}', '----output-paths', + /tmp/outputs/test_accuracy/data] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - | + def show_results(test_acc): + return([test_acc]) + + def _serialize_float(float_value: float) -> str: + if isinstance(float_value, str): + return float_value + if not isinstance(float_value, (float, int)): + raise TypeError('Value "{}" has type "{}" instead of float.'.format( + str(float_value), str(type(float_value)))) + return str(float_value) + + import argparse + _parser = argparse.ArgumentParser(prog='Show results', description='') + _parser.add_argument("--test-acc", dest="test_acc", type=float, required=True, default=argparse.SUPPRESS) + _parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=1) + _parsed_args = vars(_parser.parse_args()) + _output_files = _parsed_args.pop("_output_paths", []) + + _outputs = show_results(**_parsed_args) + + _output_serializers = [ + _serialize_float, + + ] + + import os + for idx, output_file in enumerate(_output_files): + try: + os.makedirs(os.path.dirname(output_file)) + except OSError: + pass + with open(output_file, 'w') as f: + f.write(_output_serializers[idx](_outputs[idx])) + image: python:3.7 + resources: + limits: {cpu: '0.2'} + requests: {cpu: '0.2'} + inputs: + parameters: + - {name: client-last_accuracy} + outputs: + artifacts: + - {name: show-results-test_accuracy, path: /tmp/outputs/test_accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--test-acc", {"inputValue": "test_acc"}, "----output-paths", + {"outputPath": "test_accuracy"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def show_results(test_acc):\n return([test_acc])\n\ndef _serialize_float(float_value: + float) -> str:\n if isinstance(float_value, str):\n return float_value\n if + not isinstance(float_value, (float, int)):\n raise TypeError(''Value + \"{}\" has type \"{}\" instead of float.''.format(\n str(float_value), + str(type(float_value))))\n return str(float_value)\n\nimport argparse\n_parser + = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--test-acc\", + dest=\"test_acc\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = show_results(**_parsed_args)\n\n_output_serializers + = [\n _serialize_float,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "python:3.7"}}, "inputs": [{"name": "test_acc", "type": "Float"}], + "name": "Show results", "outputs": [{"name": "test_accuracy", "type": "Float"}]}', + pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"test_acc": + "{{inputs.parameters.client-last_accuracy}}"}'} + arguments: + parameters: + - {name: namespace, value: kubeflow-user-thu01} + serviceAccountName: pipeline-runner diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml new file mode 100644 index 000000000..b8f353c80 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/mnist_pipeline.yaml @@ -0,0 +1,211 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: mnist-pipeline- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-12-26T13:06:02.352865', + pipelines.kubeflow.org/pipeline_spec: '{"description": "A pipeline to train a + model on mnist dataset and start a tensorboard.", "name": "mnist pipeline"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} +spec: + entrypoint: mnist-pipeline + templates: + - name: create-tensorboard-visualization + container: + args: [] + command: + - sh + - -ex + - -c + - | + log_dir="$0" + output_metadata_path="$1" + pod_template_spec="$2" + image="$3" + + mkdir -p "$(dirname "$output_metadata_path")" + + echo ' + { + "outputs" : [{ + "type": "tensorboard", + "source": "'"$log_dir"'", + "image": "'"$image"'", + "pod_template_spec": '"$pod_template_spec"' + }] + } + ' >"$output_metadata_path" + - volume://mypvc/logs + - /tmp/outputs/mlpipeline-ui-metadata/data + - '{"spec": {"containers": [{"volumeMounts": [{"mountPath": "/data", "name": + "mypvc"}], "resources": {"requests": {"cpu": "250m"}, "limits": {"cpu": "500m"}}}], + "serviceAccountName": "default-editor", "volumes": [{"name": "mypvc", "persistentVolumeClaim": + {"claimName": "my-awesome-kf-workshop-1703595962"}}]}}' + - footprintai/tensorboard:2.7.0 + image: alpine + resources: + limits: {cpu: '1'} + requests: {cpu: '1'} + outputs: + artifacts: + - {name: mlpipeline-ui-metadata, path: /tmp/outputs/mlpipeline-ui-metadata/data} + metadata: + annotations: {author: Alexey Volkov , canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/tensorboard/prepare_tensorboard/component.yaml', + pipelines.kubeflow.org/component_spec: '{"description": "Pre-creates Tensorboard + visualization for a given Log dir URI.\nThis way the Tensorboard can be + viewed before the training completes.\nThe output Log dir URI should be + passed to a trainer component that will write Tensorboard logs to that directory.\n", + "implementation": {"container": {"command": ["sh", "-ex", "-c", "log_dir=\"$0\"\noutput_metadata_path=\"$1\"\npod_template_spec=\"$2\"\nimage=\"$3\"\n\nmkdir + -p \"$(dirname \"$output_metadata_path\")\"\n\necho ''\n {\n \"outputs\" + : [{\n \"type\": \"tensorboard\",\n \"source\": \"''\"$log_dir\"''\",\n \"image\": + \"''\"$image\"''\",\n \"pod_template_spec\": ''\"$pod_template_spec\"''\n }]\n }\n'' + >\"$output_metadata_path\"\n", {"inputValue": "Log dir URI"}, {"outputPath": + "mlpipeline-ui-metadata"}, {"inputValue": "Pod Template Spec"}, {"inputValue": + "Image"}], "image": "alpine"}}, "inputs": [{"name": "Log dir URI", "type": + "String"}, {"default": "", "name": "Image", "type": "String"}, {"default": + "null", "name": "Pod Template Spec", "type": "String"}], "metadata": {"annotations": + {"author": "Alexey Volkov ", "canonical_location": + "https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/tensorboard/prepare_tensorboard/component.yaml"}}, + "name": "Create Tensorboard visualization", "outputs": [{"name": "mlpipeline-ui-metadata", + "type": "kfp.v1.ui-metadata"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "cc3c37c54619129e4f57e4564bc5df0ba9719a305e6145238f2ae7e54d87f2ef", "url": + "https://raw.githubusercontent.com/kubeflow/pipelines/1b107eb4bb2510ecb99fd5f4fb438cbf7c96a87a/components/contrib/tensorflow/tensorboard/prepare_tensorboard/component.yaml"}', + pipelines.kubeflow.org/arguments.parameters: '{"Image": "footprintai/tensorboard:2.7.0", + "Log dir URI": "volume://mypvc/logs", "Pod Template Spec": "{\"spec\": {\"containers\": + [{\"volumeMounts\": [{\"mountPath\": \"/data\", \"name\": \"mypvc\"}], \"resources\": + {\"requests\": {\"cpu\": \"250m\"}, \"limits\": {\"cpu\": \"500m\"}}}], + \"serviceAccountName\": \"default-editor\", \"volumes\": [{\"name\": \"mypvc\", + \"persistentVolumeClaim\": {\"claimName\": \"my-awesome-kf-workshop-1703595962\"}}]}}"}'} + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + - name: mnist-func + container: + args: [--log-folder, /data, '----output-paths', /tmp/outputs/logdir/data] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - "def mnist_func(log_folder):\n\n print('mnist_func:', log_folder)\n \ + \ import tensorflow as tf\n import json\n mnist = tf.keras.datasets.mnist\n\ + \ (x_train,y_train), (x_test, y_test) = mnist.load_data()\n x_train,\ + \ x_test = x_train/255.0, x_test/255.0\n\n def create_model():\n \ + \ return tf.keras.models.Sequential([\n tf.keras.layers.Flatten(input_shape\ + \ = (28,28)),\n tf.keras.layers.Dense(512, activation = 'relu'),\n\ + \ tf.keras.layers.Dropout(0.2),\n tf.keras.layers.Dense(10,\ + \ activation = 'softmax')\n ])\n model = create_model()\n model.compile(optimizer='adam',\n\ + \ loss='sparse_categorical_crossentropy',\n \ + \ metrics=['accuracy'])\n import datetime\n import os\n\n ###\ + \ add tensorboard logout callback\n log_dir = os.path.join(log_folder,\ + \ \"logs\", datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n tensorboard_callback\ + \ = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n \ + \ ######\n\n model.fit(x=x_train, \n y=y_train, \n \ + \ epochs=5, \n validation_data=(x_test, y_test), \n \ + \ callbacks=[tensorboard_callback])\n\n print('At least tensorboard\ + \ callbacks are correct')\n print('logdir:', log_dir)\n return ([log_dir])\n\ + \ndef _serialize_str(str_value: str) -> str:\n if not isinstance(str_value,\ + \ str):\n raise TypeError('Value \"{}\" has type \"{}\" instead of\ + \ str.'.format(\n str(str_value), str(type(str_value))))\n return\ + \ str_value\n\nimport argparse\n_parser = argparse.ArgumentParser(prog='Mnist\ + \ func', description='')\n_parser.add_argument(\"--log-folder\", dest=\"log_folder\"\ + , type=str, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"\ + ----output-paths\", dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args\ + \ = vars(_parser.parse_args())\n_output_files = _parsed_args.pop(\"_output_paths\"\ + , [])\n\n_outputs = mnist_func(**_parsed_args)\n\n_output_serializers = [\n\ + \ _serialize_str,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n\ + \ try:\n os.makedirs(os.path.dirname(output_file))\n except OSError:\n\ + \ pass\n with open(output_file, 'w') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n" + image: tensorflow/tensorflow:2.0.0-py3 + resources: + limits: {cpu: '1'} + requests: {cpu: '1'} + volumeMounts: + - {mountPath: /data, name: mypvc} + inputs: + parameters: + - {name: mypvc-name} + outputs: + artifacts: + - {name: mnist-func-logdir, path: /tmp/outputs/logdir/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--log-folder", {"inputValue": "log_folder"}, "----output-paths", + {"outputPath": "logdir"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def mnist_func(log_folder):\n\n print(''mnist_func:'', log_folder)\n import + tensorflow as tf\n import json\n mnist = tf.keras.datasets.mnist\n (x_train,y_train), + (x_test, y_test) = mnist.load_data()\n x_train, x_test = x_train/255.0, + x_test/255.0\n\n def create_model():\n return tf.keras.models.Sequential([\n tf.keras.layers.Flatten(input_shape + = (28,28)),\n tf.keras.layers.Dense(512, activation = ''relu''),\n tf.keras.layers.Dropout(0.2),\n tf.keras.layers.Dense(10, + activation = ''softmax'')\n ])\n model = create_model()\n model.compile(optimizer=''adam'',\n loss=''sparse_categorical_crossentropy'',\n metrics=[''accuracy''])\n import + datetime\n import os\n\n ### add tensorboard logout callback\n log_dir + = os.path.join(log_folder, \"logs\", datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n tensorboard_callback + = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n ######\n\n model.fit(x=x_train, + \n y=y_train, \n epochs=5, \n validation_data=(x_test, + y_test), \n callbacks=[tensorboard_callback])\n\n print(''At + least tensorboard callbacks are correct'')\n print(''logdir:'', log_dir)\n return + ([log_dir])\n\ndef _serialize_str(str_value: str) -> str:\n if not isinstance(str_value, + str):\n raise TypeError(''Value \"{}\" has type \"{}\" instead of + str.''.format(\n str(str_value), str(type(str_value))))\n return + str_value\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Mnist + func'', description='''')\n_parser.add_argument(\"--log-folder\", dest=\"log_folder\", + type=str, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"----output-paths\", + dest=\"_output_paths\", type=str, nargs=1)\n_parsed_args = vars(_parser.parse_args())\n_output_files + = _parsed_args.pop(\"_output_paths\", [])\n\n_outputs = mnist_func(**_parsed_args)\n\n_output_serializers + = [\n _serialize_str,\n\n]\n\nimport os\nfor idx, output_file in enumerate(_output_files):\n try:\n os.makedirs(os.path.dirname(output_file))\n except + OSError:\n pass\n with open(output_file, ''w'') as f:\n f.write(_output_serializers[idx](_outputs[idx]))\n"], + "image": "tensorflow/tensorflow:2.0.0-py3"}}, "inputs": [{"name": "log_folder", + "type": "String"}], "name": "Mnist func", "outputs": [{"name": "logdir", + "type": "String"}]}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"log_folder": + "/data"}'} + volumes: + - name: mypvc + persistentVolumeClaim: {claimName: '{{inputs.parameters.mypvc-name}}'} + - name: mnist-pipeline + dag: + tasks: + - {name: create-tensorboard-visualization, template: create-tensorboard-visualization} + - name: mnist-func + template: mnist-func + dependencies: [create-tensorboard-visualization, mypvc] + arguments: + parameters: + - {name: mypvc-name, value: '{{tasks.mypvc.outputs.parameters.mypvc-name}}'} + - {name: mypvc, template: mypvc} + - name: mypvc + resource: + action: create + manifest: | + apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: '{{workflow.name}}-my-awesome-kf-workshop-1703595962' + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + outputs: + parameters: + - name: mypvc-manifest + valueFrom: {jsonPath: '{}'} + - name: mypvc-name + valueFrom: {jsonPath: '{.metadata.name}'} + - name: mypvc-size + valueFrom: {jsonPath: '{.status.capacity.storage}'} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + arguments: + parameters: [] + serviceAccountName: pipeline-runner diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml new file mode 100644 index 000000000..b1a4a1e25 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/only_decision_tree.yaml @@ -0,0 +1,131 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: only-decision-tree- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T21:42:00.682134', + pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Decision Tree + for classification problem.", "name": "only_decision_tree"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.20} +spec: + entrypoint: only-decision-tree + templates: + - name: decision-tree-classifier + container: + args: [] + command: [python, decision_tree.py, --data, /tmp/inputs/Data/data, --accuracy, + /tmp/outputs/Accuracy/data] + image: lightnighttw/kubeflow:decision_tree_v2 + resources: + limits: + cpu: 2 + inputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/inputs/Data/data} + outputs: + parameters: + - name: decision-tree-classifier-Accuracy + valueFrom: {path: /tmp/outputs/Accuracy/data} + artifacts: + - {name: decision-tree-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains + a decision tree classifier", "implementation": {"container": {"command": + ["python", "decision_tree.py", "--data", {"inputPath": "Data"}, "--accuracy", + {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:decision_tree_v2"}}, + "inputs": [{"description": "Path where data is stored.", "name": "Data", + "type": "LocalPath"}], "name": "Decision Tree classifier", "outputs": [{"description": + "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "c5c232a9654213b3b222693949b71a5d561d04ed09543c20b6f8f2eab651ae0b", "url": + "decision_tree/decision_tree.yaml"}'} + - name: download-data-function + container: + args: [] + command: [python, download_data.py, --data, /tmp/outputs/Data/data] + image: lightnighttw/kubeflow:download_data + resources: + limits: + cpu: 2 + outputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/outputs/Data/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download + toy data from sklearn datasets", "implementation": {"container": {"command": + ["python", "download_data.py", "--data", {"outputPath": "Data"}], "image": + "lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function", + "outputs": [{"description": "Path where data will be stored.", "name": "Data", + "type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url": + "download_data/download_data.yaml"}'} + - name: only-decision-tree + dag: + tasks: + - name: decision-tree-classifier + template: decision-tree-classifier + dependencies: [download-data-function] + arguments: + artifacts: + - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} + - {name: download-data-function, template: download-data-function} + - name: show-results + template: show-results + dependencies: [decision-tree-classifier] + arguments: + parameters: + - {name: decision-tree-classifier-Accuracy, value: '{{tasks.decision-tree-classifier.outputs.parameters.decision-tree-classifier-Accuracy}}'} + - name: show-results + container: + args: [--decision-tree, '{{inputs.parameters.decision-tree-classifier-Accuracy}}'] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - | + def show_results(decision_tree): + # the results are shown. + + print(f"Decision tree (accuracy): {decision_tree}") + + import argparse + _parser = argparse.ArgumentParser(prog='Show results', description='') + _parser.add_argument("--decision-tree", dest="decision_tree", type=float, required=True, default=argparse.SUPPRESS) + _parsed_args = vars(_parser.parse_args()) + + _outputs = show_results(**_parsed_args) + image: python:3.7 + resources: + limits: + cpu: 2 + inputs: + parameters: + - {name: decision-tree-classifier-Accuracy} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.20 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--decision-tree", {"inputValue": "decision_tree"}], "command": + ["sh", "-ec", "program_path=$(mktemp)\nprintf \"%s\" \"$0\" > \"$program_path\"\npython3 + -u \"$program_path\" \"$@\"\n", "def show_results(decision_tree):\n # + the results are shown.\n\n print(f\"Decision tree (accuracy): {decision_tree}\")\n\nimport + argparse\n_parser = argparse.ArgumentParser(prog=''Show results'', description='''')\n_parser.add_argument(\"--decision-tree\", + dest=\"decision_tree\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args + = vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"], + "image": "python:3.7"}}, "inputs": [{"name": "decision_tree", "type": "Float"}], + "name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}', pipelines.kubeflow.org/arguments.parameters: '{"decision_tree": + "{{inputs.parameters.decision-tree-classifier-Accuracy}}"}'} + arguments: + parameters: [] + serviceAccountName: pipeline-runner diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml new file mode 100644 index 000000000..2e10bcefa --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/pipelines/three-pipeline.yaml @@ -0,0 +1,229 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: three-pipeline- + annotations: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9, pipelines.kubeflow.org/pipeline_compilation_time: '2023-04-28T12:05:44.365082', + pipelines.kubeflow.org/pipeline_spec: '{"description": "Applies Decision Tree, + random forest and Logistic Regression for classification problem.", "name": + "Three Pipeline"}'} + labels: {pipelines.kubeflow.org/kfp_sdk_version: 1.8.9} +spec: + entrypoint: three-pipeline + templates: + - name: decision-tree-classifier + container: + args: [] + command: [python, decision_tree.py, --data, /tmp/inputs/Data/data, --accuracy, + /tmp/outputs/Accuracy/data] + image: lightnighttw/kubeflow:decision_tree_v2 + resources: + limits: + cpu: 2 + inputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/inputs/Data/data} + outputs: + parameters: + - name: decision-tree-classifier-Accuracy + valueFrom: {path: /tmp/outputs/Accuracy/data} + artifacts: + - {name: decision-tree-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains + a decision tree classifier", "implementation": {"container": {"command": + ["python", "decision_tree.py", "--data", {"inputPath": "Data"}, "--accuracy", + {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:decision_tree_v2"}}, + "inputs": [{"description": "Path where data is stored.", "name": "Data", + "type": "LocalPath"}], "name": "Decision Tree classifier", "outputs": [{"description": + "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "c5c232a9654213b3b222693949b71a5d561d04ed09543c20b6f8f2eab651ae0b", "url": + "decision_tree/decision_tree.yaml"}'} + - name: download-data-function + container: + args: [] + command: [python, download_data.py, --data, /tmp/outputs/Data/data] + image: lightnighttw/kubeflow:download_data + resources: + limits: + cpu: 2 + outputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/outputs/Data/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Download + toy data from sklearn datasets", "implementation": {"container": {"command": + ["python", "download_data.py", "--data", {"outputPath": "Data"}], "image": + "lightnighttw/kubeflow:download_data"}}, "name": "Download Data Function", + "outputs": [{"description": "Path where data will be stored.", "name": "Data", + "type": "LocalPath"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "467750defdccfec51c3af2a7eb853f74235f5f97329006d72bf33ff6e15ed02d", "url": + "download_data/download_data.yaml"}'} + - name: logistic-regression-classifier + container: + args: [] + command: [python, logistic_regression.py, --data, /tmp/inputs/Data/data, --accuracy, + /tmp/outputs/Accuracy/data] + image: lightnighttw/kubeflow:logistic_regression + resources: + limits: + cpu: 2 + inputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/inputs/Data/data} + outputs: + parameters: + - name: logistic-regression-classifier-Accuracy + valueFrom: {path: /tmp/outputs/Accuracy/data} + artifacts: + - {name: logistic-regression-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Trains + a Logistic Regression Classifier", "implementation": {"container": {"command": + ["python", "logistic_regression.py", "--data", {"inputPath": "Data"}, "--accuracy", + {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:logistic_regression"}}, + "inputs": [{"description": "Path where data is stored.", "name": "Data", + "type": "LocalPath"}], "name": "Logistic Regression Classifier", "outputs": + [{"description": "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', + pipelines.kubeflow.org/component_ref: '{"digest": "a8d1e77d07d18a75bef200aee96f35136833fc4bb535f33fd949a307beb094c2", + "url": "logistic_regression/logistic_regression.yaml"}'} + - name: random-forest-classifier + container: + args: [] + command: [python, randomforest.py, --data, /tmp/inputs/Data/data, --accuracy, + /tmp/outputs/Accuracy/data] + image: lightnighttw/kubeflow:random_forest_v4 + resources: + limits: + cpu: 2 + inputs: + artifacts: + - {name: download-data-function-Data, path: /tmp/inputs/Data/data} + outputs: + parameters: + - name: random-forest-classifier-Accuracy + valueFrom: {path: /tmp/outputs/Accuracy/data} + artifacts: + - {name: random-forest-classifier-Accuracy, path: /tmp/outputs/Accuracy/data} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"description": "Train + a random forest classifier", "implementation": {"container": {"command": + ["python", "randomforest.py", "--data", {"inputPath": "Data"}, "--accuracy", + {"outputPath": "Accuracy"}], "image": "lightnighttw/kubeflow:random_forest_v4"}}, + "inputs": [{"description": "Path where data is stored.", "name": "Data", + "type": "LocalPath"}], "name": "Random Forest classifier", "outputs": [{"description": + "Accuracy metric", "name": "Accuracy", "type": "Float"}]}', pipelines.kubeflow.org/component_ref: '{"digest": + "b49b12da3371976eddf41d662685bb49d71b419d516de65efdd90938d2c706bc", "url": + "randomForest/random_forest.yaml"}'} + - name: show-results + container: + args: [--decision-tree, '{{inputs.parameters.decision-tree-classifier-Accuracy}}', + --logistic-regression, '{{inputs.parameters.logistic-regression-classifier-Accuracy}}', + --random-forest, '{{inputs.parameters.random-forest-classifier-Accuracy}}'] + command: + - sh + - -ec + - | + program_path=$(mktemp) + printf "%s" "$0" > "$program_path" + python3 -u "$program_path" "$@" + - | + def show_results(decision_tree, logistic_regression, random_forest): + # Given the outputs from decision_tree and logistic regression components + # the results are shown. + + print(f"Decision tree (accuracy): {decision_tree}") + print(f"Logistic regression (accuracy): {logistic_regression}") + print(f"Random forest (accuracy): {random_forest}") + + import argparse + _parser = argparse.ArgumentParser(prog='Show results', description='') + _parser.add_argument("--decision-tree", dest="decision_tree", type=float, required=True, default=argparse.SUPPRESS) + _parser.add_argument("--logistic-regression", dest="logistic_regression", type=float, required=True, default=argparse.SUPPRESS) + _parser.add_argument("--random-forest", dest="random_forest", type=float, required=True, default=argparse.SUPPRESS) + _parsed_args = vars(_parser.parse_args()) + + _outputs = show_results(**_parsed_args) + image: python:3.7 + resources: + limits: + cpu: 2 + inputs: + parameters: + - {name: decision-tree-classifier-Accuracy} + - {name: logistic-regression-classifier-Accuracy} + - {name: random-forest-classifier-Accuracy} + metadata: + labels: + pipelines.kubeflow.org/kfp_sdk_version: 1.8.9 + pipelines.kubeflow.org/pipeline-sdk-type: kfp + pipelines.kubeflow.org/enable_caching: "true" + annotations: {pipelines.kubeflow.org/component_spec: '{"implementation": {"container": + {"args": ["--decision-tree", {"inputValue": "decision_tree"}, "--logistic-regression", + {"inputValue": "logistic_regression"}, "--random-forest", {"inputValue": + "random_forest"}], "command": ["sh", "-ec", "program_path=$(mktemp)\nprintf + \"%s\" \"$0\" > \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n", + "def show_results(decision_tree, logistic_regression, random_forest):\n # + Given the outputs from decision_tree and logistic regression components\n # + the results are shown.\n\n print(f\"Decision tree (accuracy): {decision_tree}\")\n print(f\"Logistic + regression (accuracy): {logistic_regression}\")\n print(f\"Random forest + (accuracy): {random_forest}\")\n\nimport argparse\n_parser = argparse.ArgumentParser(prog=''Show + results'', description='''')\n_parser.add_argument(\"--decision-tree\", + dest=\"decision_tree\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"--logistic-regression\", + dest=\"logistic_regression\", type=float, required=True, default=argparse.SUPPRESS)\n_parser.add_argument(\"--random-forest\", + dest=\"random_forest\", type=float, required=True, default=argparse.SUPPRESS)\n_parsed_args + = vars(_parser.parse_args())\n\n_outputs = show_results(**_parsed_args)\n"], + "image": "python:3.7"}}, "inputs": [{"name": "decision_tree", "type": "Float"}, + {"name": "logistic_regression", "type": "Float"}, {"name": "random_forest", + "type": "Float"}], "name": "Show results"}', pipelines.kubeflow.org/component_ref: '{}', + pipelines.kubeflow.org/arguments.parameters: '{"decision_tree": "{{inputs.parameters.decision-tree-classifier-Accuracy}}", + "logistic_regression": "{{inputs.parameters.logistic-regression-classifier-Accuracy}}", + "random_forest": "{{inputs.parameters.random-forest-classifier-Accuracy}}"}'} + - name: three-pipeline + dag: + tasks: + - name: decision-tree-classifier + template: decision-tree-classifier + dependencies: [download-data-function] + arguments: + artifacts: + - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} + - {name: download-data-function, template: download-data-function} + - name: logistic-regression-classifier + template: logistic-regression-classifier + dependencies: [download-data-function] + arguments: + artifacts: + - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} + - name: random-forest-classifier + template: random-forest-classifier + dependencies: [download-data-function] + arguments: + artifacts: + - {name: download-data-function-Data, from: '{{tasks.download-data-function.outputs.artifacts.download-data-function-Data}}'} + - name: show-results + template: show-results + dependencies: [decision-tree-classifier, logistic-regression-classifier, random-forest-classifier] + arguments: + parameters: + - {name: decision-tree-classifier-Accuracy, value: '{{tasks.decision-tree-classifier.outputs.parameters.decision-tree-classifier-Accuracy}}'} + - {name: logistic-regression-classifier-Accuracy, value: '{{tasks.logistic-regression-classifier.outputs.parameters.logistic-regression-classifier-Accuracy}}'} + - {name: random-forest-classifier-Accuracy, value: '{{tasks.random-forest-classifier.outputs.parameters.random-forest-classifier-Accuracy}}'} + arguments: + parameters: [] + serviceAccountName: pipeline-runner diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/requirements.txt b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/requirements.txt new file mode 100644 index 000000000..0a8547bcc --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/py/requirements.txt @@ -0,0 +1,2 @@ +setuptools +wheel diff --git a/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/settings.js b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/settings.js new file mode 100644 index 000000000..332013ee1 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/1.connect-kubeflow/settings.js @@ -0,0 +1,498 @@ +/** + * This is the default settings file provided by Node-RED. + * + * It can contain any valid JavaScript code that will get run when Node-RED + * is started. + * + * Lines that start with // are commented out. + * Each entry should be separated from the entries above and below by a comma ',' + * + * For more information about individual settings, refer to the documentation: + * https://nodered.org/docs/user-guide/runtime/configuration + * + * The settings are split into the following sections: + * - Flow File and User Directory Settings + * - Security + * - Server Settings + * - Runtime Settings + * - Editor Settings + * - Node Settings + * + **/ + +module.exports = { + +/******************************************************************************* + * Flow File and User Directory Settings + * - flowFile + * - credentialSecret + * - flowFilePretty + * - userDir + * - nodesDir + ******************************************************************************/ + + /** The file containing the flows. If not set, defaults to flows_.json **/ + flowFile: 'flows.json', + + /** By default, credentials are encrypted in storage using a generated key. To + * specify your own secret, set the following property. + * If you want to disable encryption of credentials, set this property to false. + * Note: once you set this property, do not change it - doing so will prevent + * node-red from being able to decrypt your existing credentials and they will be + * lost. + */ + //credentialSecret: "a-secret-key", + credentialSecret: process.env.NODE_RED_CREDENTIAL_SECRET, + + /** By default, the flow JSON will be formatted over multiple lines making + * it easier to compare changes when using version control. + * To disable pretty-printing of the JSON set the following property to false. + */ + flowFilePretty: true, + + /** By default, all user data is stored in a directory called `.node-red` under + * the user's home directory. To use a different location, the following + * property can be used + */ + //userDir: '/home/nol/.node-red/', + + /** Node-RED scans the `nodes` directory in the userDir to find local node files. + * The following property can be used to specify an additional directory to scan. + */ + //nodesDir: '/home/nol/.node-red/nodes', + +/******************************************************************************* + * Security + * - adminAuth + * - https + * - httpsRefreshInterval + * - requireHttps + * - httpNodeAuth + * - httpStaticAuth + ******************************************************************************/ + + /** To password protect the Node-RED editor and admin API, the following + * property can be used. See http://nodered.org/docs/security.html for details. + */ + //adminAuth: { + // type: "credentials", + // users: [{ + // username: "admin", + // password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.", + // permissions: "*" + // }] + //}, + + /** The following property can be used to enable HTTPS + * This property can be either an object, containing both a (private) key + * and a (public) certificate, or a function that returns such an object. + * See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener + * for details of its contents. + */ + + /** Option 1: static object */ + //https: { + // key: require("fs").readFileSync('privkey.pem'), + // cert: require("fs").readFileSync('cert.pem') + //}, + + /** Option 2: function that returns the HTTP configuration object */ + // https: function() { + // // This function should return the options object, or a Promise + // // that resolves to the options object + // return { + // key: require("fs").readFileSync('privkey.pem'), + // cert: require("fs").readFileSync('cert.pem') + // } + // }, + + /** If the `https` setting is a function, the following setting can be used + * to set how often, in hours, the function will be called. That can be used + * to refresh any certificates. + */ + //httpsRefreshInterval : 12, + + /** The following property can be used to cause insecure HTTP connections to + * be redirected to HTTPS. + */ + //requireHttps: true, + + /** To password protect the node-defined HTTP endpoints (httpNodeRoot), + * including node-red-dashboard, or the static content (httpStatic), the + * following properties can be used. + * The `pass` field is a bcrypt hash of the password. + * See http://nodered.org/docs/security.html#generating-the-password-hash + */ + //httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + //httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + +/******************************************************************************* + * Server Settings + * - uiPort + * - uiHost + * - apiMaxLength + * - httpServerOptions + * - httpAdminRoot + * - httpAdminMiddleware + * - httpNodeRoot + * - httpNodeCors + * - httpNodeMiddleware + * - httpStatic + ******************************************************************************/ + + /** the tcp port that the Node-RED web server is listening on */ + uiPort: process.env.PORT || 1880, + + /** By default, the Node-RED UI accepts connections on all IPv4 interfaces. + * To listen on all IPv6 addresses, set uiHost to "::", + * The following property can be used to listen on a specific interface. For + * example, the following would only allow connections from the local machine. + */ + //uiHost: "127.0.0.1", + + /** The maximum size of HTTP request that will be accepted by the runtime api. + * Default: 5mb + */ + //apiMaxLength: '5mb', + + /** The following property can be used to pass custom options to the Express.js + * server used by Node-RED. For a full list of available options, refer + * to http://expressjs.com/en/api.html#app.settings.table + */ + //httpServerOptions: { }, + + /** By default, the Node-RED UI is available at http://localhost:1880/ + * The following property can be used to specify a different root path. + * If set to false, this is disabled. + */ + //httpAdminRoot: '/admin', + + /** The following property can be used to add a custom middleware function + * in front of all admin http routes. For example, to set custom http + * headers. It can be a single function or an array of middleware functions. + */ + // httpAdminMiddleware: function(req,res,next) { + // // Set the X-Frame-Options header to limit where the editor + // // can be embedded + // //res.set('X-Frame-Options', 'sameorigin'); + // next(); + // }, + + + /** Some nodes, such as HTTP In, can be used to listen for incoming http requests. + * By default, these are served relative to '/'. The following property + * can be used to specifiy a different root path. If set to false, this is + * disabled. + */ + //httpNodeRoot: '/red-nodes', + + /** The following property can be used to configure cross-origin resource sharing + * in the HTTP nodes. + * See https://github.com/troygoode/node-cors#configuration-options for + * details on its contents. The following is a basic permissive set of options: + */ + //httpNodeCors: { + // origin: "*", + // methods: "GET,PUT,POST,DELETE" + //}, + + /** If you need to set an http proxy please set an environment variable + * called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system. + * For example - http_proxy=http://myproxy.com:8080 + * (Setting it here will have no effect) + * You may also specify no_proxy (or NO_PROXY) to supply a comma separated + * list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk + */ + + /** The following property can be used to add a custom middleware function + * in front of all http in nodes. This allows custom authentication to be + * applied to all http in nodes, or any other sort of common request processing. + * It can be a single function or an array of middleware functions. + */ + //httpNodeMiddleware: function(req,res,next) { + // // Handle/reject the request, or pass it on to the http in node by calling next(); + // // Optionally skip our rawBodyParser by setting this to true; + // //req.skipRawBodyParser = true; + // next(); + //}, + + /** When httpAdminRoot is used to move the UI to a different root path, the + * following property can be used to identify a directory of static content + * that should be served at http://localhost:1880/. + */ + //httpStatic: '/home/nol/node-red-static/', + +/******************************************************************************* + * Runtime Settings + * - lang + * - logging + * - contextStorage + * - exportGlobalContextKeys + * - externalModules + ******************************************************************************/ + + /** Uncomment the following to run node-red in your preferred language. + * Available languages include: en-US (default), ja, de, zh-CN, zh-TW, ru, ko + * Some languages are more complete than others. + */ + // lang: "de", + + /** Configure the logging output */ + logging: { + /** Only console logging is currently supported */ + console: { + /** Level of logging to be recorded. Options are: + * fatal - only those errors which make the application unusable should be recorded + * error - record errors which are deemed fatal for a particular request + fatal errors + * warn - record problems which are non fatal + errors + fatal errors + * info - record information about the general running of the application + warn + error + fatal errors + * debug - record information which is more verbose than info + info + warn + error + fatal errors + * trace - record very detailed logging + debug + info + warn + error + fatal errors + * off - turn off all logging (doesn't affect metrics or audit) + */ + level: "info", + /** Whether or not to include metric events in the log output */ + metrics: false, + /** Whether or not to include audit events in the log output */ + audit: false + } + }, + + /** Context Storage + * The following property can be used to enable context storage. The configuration + * provided here will enable file-based context that flushes to disk every 30 seconds. + * Refer to the documentation for further options: https://nodered.org/docs/api/context/ + */ + //contextStorage: { + // default: { + // module:"localfilesystem" + // }, + //}, + + /** `global.keys()` returns a list of all properties set in global context. + * This allows them to be displayed in the Context Sidebar within the editor. + * In some circumstances it is not desirable to expose them to the editor. The + * following property can be used to hide any property set in `functionGlobalContext` + * from being list by `global.keys()`. + * By default, the property is set to false to avoid accidental exposure of + * their values. Setting this to true will cause the keys to be listed. + */ + exportGlobalContextKeys: false, + + /** Configure how the runtime will handle external npm modules. + * This covers: + * - whether the editor will allow new node modules to be installed + * - whether nodes, such as the Function node are allowed to have their + * own dynamically configured dependencies. + * The allow/denyList options can be used to limit what modules the runtime + * will install/load. It can use '*' as a wildcard that matches anything. + */ + externalModules: { + // autoInstall: false, /** Whether the runtime will attempt to automatically install missing modules */ + // autoInstallRetry: 30, /** Interval, in seconds, between reinstall attempts */ + // palette: { /** Configuration for the Palette Manager */ + // allowInstall: true, /** Enable the Palette Manager in the editor */ + // allowUpdate: true, /** Allow modules to be updated in the Palette Manager */ + // allowUpload: true, /** Allow module tgz files to be uploaded and installed */ + // allowList: ['*'], + // denyList: [], + // allowUpdateList: ['*'], + // denyUpdateList: [] + // }, + // modules: { /** Configuration for node-specified modules */ + // allowInstall: true, + // allowList: [], + // denyList: [] + // } + }, + + +/******************************************************************************* + * Editor Settings + * - disableEditor + * - editorTheme + ******************************************************************************/ + + /** The following property can be used to disable the editor. The admin API + * is not affected by this option. To disable both the editor and the admin + * API, use either the httpRoot or httpAdminRoot properties + */ + //disableEditor: false, + + /** Customising the editor + * See https://nodered.org/docs/user-guide/runtime/configuration#editor-themes + * for all available options. + */ + editorTheme: { + /** The following property can be used to set a custom theme for the editor. + * See https://github.com/node-red-contrib-themes/theme-collection for + * a collection of themes to chose from. + */ + //theme: "", + + /** To disable the 'Welcome to Node-RED' tour that is displayed the first + * time you access the editor for each release of Node-RED, set this to false + */ + //tours: false, + + palette: { + /** The following property can be used to order the categories in the editor + * palette. If a node's category is not in the list, the category will get + * added to the end of the palette. + * If not set, the following default order is used: + */ + //categories: ['subflows', 'common', 'function', 'network', 'sequence', 'parser', 'storage'], + }, + + projects: { + /** To enable the Projects feature, set this value to true */ + enabled: false, + workflow: { + /** Set the default projects workflow mode. + * - manual - you must manually commit changes + * - auto - changes are automatically committed + * This can be overridden per-user from the 'Git config' + * section of 'User Settings' within the editor + */ + mode: "manual" + } + }, + + codeEditor: { + /** Select the text editor component used by the editor. + * Defaults to "ace", but can be set to "ace" or "monaco" + */ + lib: "ace", + options: { + /** The follow options only apply if the editor is set to "monaco" + * + * theme - must match the file name of a theme in + * packages/node_modules/@node-red/editor-client/src/vendor/monaco/dist/theme + * e.g. "tomorrow-night", "upstream-sunburst", "github", "my-theme" + */ + theme: "vs", + /** other overrides can be set e.g. fontSize, fontFamily, fontLigatures etc. + * for the full list, see https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandaloneeditorconstructionoptions.html + */ + //fontSize: 14, + //fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace", + //fontLigatures: true, + } + } + }, + +/******************************************************************************* + * Node Settings + * - fileWorkingDirectory + * - functionGlobalContext + * - functionExternalModules + * - nodeMessageBufferMaxLength + * - ui (for use with Node-RED Dashboard) + * - debugUseColors + * - debugMaxLength + * - execMaxBufferSize + * - httpRequestTimeout + * - mqttReconnectTime + * - serialReconnectTime + * - socketReconnectTime + * - socketTimeout + * - tcpMsgQueueSize + * - inboundWebSocketTimeout + * - tlsConfigDisableLocalFiles + * - webSocketNodeVerifyClient + ******************************************************************************/ + + /** The working directory to handle relative file paths from within the File nodes + * defaults to the working directory of the Node-RED process. + */ + //fileWorkingDirectory: "", + + /** Allow the Function node to load additional npm modules directly */ + functionExternalModules: true, + + /** The following property can be used to set predefined values in Global Context. + * This allows extra node modules to be made available with in Function node. + * For example, the following: + * functionGlobalContext: { os:require('os') } + * will allow the `os` module to be accessed in a Function node using: + * global.get("os") + */ + functionGlobalContext: { + // os:require('os'), + }, + + /** The maximum number of messages nodes will buffer internally as part of their + * operation. This applies across a range of nodes that operate on message sequences. + * defaults to no limit. A value of 0 also means no limit is applied. + */ + //nodeMessageBufferMaxLength: 0, + + /** If you installed the optional node-red-dashboard you can set it's path + * relative to httpNodeRoot + * Other optional properties include + * readOnly:{boolean}, + * middleware:{function or array}, (req,res,next) - http middleware + * ioMiddleware:{function or array}, (socket,next) - socket.io middleware + */ + //ui: { path: "ui" }, + + /** Colourise the console output of the debug node */ + //debugUseColors: true, + + /** The maximum length, in characters, of any message sent to the debug sidebar tab */ + debugMaxLength: 1000, + + /** Maximum buffer size for the exec node. Defaults to 10Mb */ + //execMaxBufferSize: 10000000, + + /** Timeout in milliseconds for HTTP request connections. Defaults to 120s */ + //httpRequestTimeout: 120000, + + /** Retry time in milliseconds for MQTT connections */ + mqttReconnectTime: 15000, + + /** Retry time in milliseconds for Serial port connections */ + serialReconnectTime: 15000, + + /** Retry time in milliseconds for TCP socket connections */ + //socketReconnectTime: 10000, + + /** Timeout in milliseconds for TCP server socket connections. Defaults to no timeout */ + //socketTimeout: 120000, + + /** Maximum number of messages to wait in queue while attempting to connect to TCP socket + * defaults to 1000 + */ + //tcpMsgQueueSize: 2000, + + /** Timeout in milliseconds for inbound WebSocket connections that do not + * match any configured node. Defaults to 5000 + */ + //inboundWebSocketTimeout: 5000, + + /** To disable the option for using local files for storing keys and + * certificates in the TLS configuration node, set this to true. + */ + //tlsConfigDisableLocalFiles: true, + + /** The following property can be used to verify websocket connection attempts. + * This allows, for example, the HTTP request headers to be checked to ensure + * they include valid authentication information. + */ + //webSocketNodeVerifyClient: function(info) { + // /** 'info' has three properties: + // * - origin : the value in the Origin header + // * - req : the HTTP request + // * - secure : true if req.connection.authorized or req.connection.encrypted is set + // * + // * The function should return true if the connection should be accepted, false otherwise. + // * + // * Alternatively, if this function is defined to accept a second argument, callback, + // * it can be used to verify the client asynchronously. + // * The callback takes three arguments: + // * - result : boolean, whether to accept the connection or not + // * - code : if result is false, the HTTP error status to return + // * - reason: if result is false, the HTTP reason string to return + // */ + //}, +} diff --git a/Tunghai-CS-project-main/kubeflow/examples/Dockerfile b/Tunghai-CS-project-main/kubeflow/examples/Dockerfile new file mode 100644 index 000000000..f195a77fd --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/Dockerfile @@ -0,0 +1,20 @@ +FROM nodered/node-red:2.2.3-12 + +ARG PREFIX + +ENV NODE_OPTIONS=--max_old_space_size=128 + +USER root + +RUN apk update && \ + apk add py3-pip + +USER node-red +# Copy package.json to the WORKDIR so npm builds all +# of your added nodes modules for Node-RED +COPY package.json . +RUN npm install --unsafe-perm --no-update-notifier --no-fund --only=production + +ADD scripts/entrypoint.sh . + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/Tunghai-CS-project-main/kubeflow/examples/README.md b/Tunghai-CS-project-main/kubeflow/examples/README.md new file mode 100644 index 000000000..c56f4dd28 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/README.md @@ -0,0 +1,40 @@ +#### Examples + +This example folder contains multiple node-red flow setups, each is isolated with a folder that allows you to run the different examples with the same settings. + +##### Add customized npm package + +You can add customized npm package via `npm install` or directly modify `packages.json`. Then rebuild your container image. + +##### Build + +Simply to run the following command to build node-red image + +``` +./build.sh +``` + +##### Run the container image + +To run the container image, use + +``` +KUBEFLOW_HOST= \ +KUBEFLOW_USERNAME= \ +KUBEFLOW_PASSWORD= \ +./run.sh +``` + +which would mount the current folder (i.e. ./example) onto the containers. We took this as a convenient step as you could change codes with node-red UI and the mounting volume allows the changes to be reflected onto your local file system. + +The example-args allows you to specify which example you want to run, for example + +``` +./run.sh 0.helloworld +``` + +would run the `0.helloworld` example. + +##### Visit vis UI + +then you can go to UI, check it out: http://127.0.0.1:1880/ diff --git a/Tunghai-CS-project-main/kubeflow/examples/build.sh b/Tunghai-CS-project-main/kubeflow/examples/build.sh new file mode 100644 index 000000000..37ad5136d --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +docker compose build diff --git a/Tunghai-CS-project-main/kubeflow/examples/docker-compose.yaml b/Tunghai-CS-project-main/kubeflow/examples/docker-compose.yaml new file mode 100644 index 000000000..2a9619477 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/docker-compose.yaml @@ -0,0 +1,33 @@ +################################################################################ +# Node-RED Stack or Compose +################################################################################ +# docker stack deploy node-red --compose-file docker-compose-node-red.yml +# docker-compose -f docker-compose-node-red.yml -p myNoderedProject up +################################################################################ +version: "3.7" + +services: + node-red: + image: reg.footprint-ai.com/public/kube-nodered:latest + build: + context: . + dockerfile: Dockerfile + labels: + # workaround around a docker-compose bug when image is also used by docker run (https://github.com/docker/compose/issues/10162) + com.docker.compose.container-number: "1" + environment: + - TZ=Asia/Taipei + - USERDIR=$USERDIR + - NODE_RED_CREDENTIAL_SECRET=noderedtutorial + - KUBEFLOW_HOST=$KUBEFLOW_HOST + - KUBEFLOW_USERNAME=$KUBEFLOW_USERNAME + - KUBEFLOW_PASSWORD=$KUBEFLOW_PASSWORD + ports: + - "1880:1880" + networks: + - node-red-net + volumes: + - ./:/data + +networks: + node-red-net: diff --git a/Tunghai-CS-project-main/kubeflow/examples/package-lock.json b/Tunghai-CS-project-main/kubeflow/examples/package-lock.json new file mode 100644 index 000000000..a333a1615 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/package-lock.json @@ -0,0 +1,10782 @@ +{ + "name": "node-red", + "version": "2.2.3", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "node-red", + "version": "2.2.3", + "license": "Apache-2.0", + "dependencies": { + "acorn": "8.7.0", + "acorn-walk": "8.2.0", + "ajv": "8.10.0", + "async-mutex": "0.3.2", + "basic-auth": "2.0.1", + "bcryptjs": "2.4.3", + "body-parser": "1.19.1", + "cheerio": "1.0.0-rc.10", + "clone": "2.1.2", + "content-type": "1.0.4", + "cookie": "0.4.2", + "cookie-parser": "1.4.6", + "cors": "2.8.5", + "cronosjs": "1.7.1", + "denque": "2.0.1", + "express": "4.17.2", + "express-session": "1.17.2", + "form-data": "4.0.0", + "fs-extra": "10.0.0", + "fs.notify": "0.0.4", + "got": "11.8.3", + "hash-sum": "2.0.0", + "hpagent": "0.1.2", + "https-proxy-agent": "5.0.0", + "i18next": "21.6.11", + "iconv-lite": "0.6.3", + "is-utf8": "0.2.1", + "js-yaml": "3.14.1", + "json-stringify-safe": "5.0.1", + "jsonata": "1.8.6", + "lodash.clonedeep": "^4.5.0", + "media-typer": "1.1.0", + "memorystore": "1.6.7", + "mime": "3.0.0", + "moment-timezone": "0.5.34", + "mqtt": "4.3.5", + "multer": "1.4.4", + "mustache": "4.2.0", + "node-red": "2.2.3", + "node-red-admin": "^2.2.3", + "node-red-contrib-pythonshell": "github:namgk/node-red-contrib-pythonshell", + "nopt": "5.0.0", + "oauth2orize": "1.11.1", + "on-headers": "1.0.2", + "passport": "0.5.2", + "passport-http-bearer": "1.0.1", + "passport-oauth2-client-password": "0.1.2", + "raw-body": "2.4.3", + "semver": "7.3.5", + "tar": "6.1.11", + "tough-cookie": "4.0.0", + "uglify-js": "3.15.1", + "uuid": "8.3.2", + "ws": "7.5.6", + "xml2js": "0.4.23" + }, + "devDependencies": { + "dompurify": "2.3.6", + "grunt": "1.5.2", + "grunt-chmod": "~1.1.1", + "grunt-cli": "~1.4.3", + "grunt-concurrent": "3.0.0", + "grunt-contrib-clean": "~2.0.0", + "grunt-contrib-compress": "2.0.0", + "grunt-contrib-concat": "~1.0.1", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-jshint": "3.1.1", + "grunt-contrib-uglify": "5.0.1", + "grunt-contrib-watch": "~1.1.0", + "grunt-jsdoc": "2.4.1", + "grunt-jsdoc-to-markdown": "6.0.0", + "grunt-jsonlint": "2.1.3", + "grunt-mkdir": "~1.1.0", + "grunt-npm-command": "~0.1.2", + "grunt-sass": "~3.1.0", + "grunt-simple-mocha": "~0.4.1", + "grunt-simple-nyc": "^3.0.1", + "i18next-http-backend": "1.3.2", + "jquery-i18next": "1.2.1", + "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", + "marked": "4.0.12", + "minami": "1.2.3", + "mocha": "9.2.0", + "node-red-node-test-helper": "^0.2.7", + "nodemon": "2.0.15", + "proxy": "^1.0.2", + "sass": "1.49.7", + "should": "13.2.3", + "sinon": "11.1.2", + "stoppable": "^1.1.0", + "supertest": "6.2.2" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", + "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", + "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.3", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.3", + "@babel/types": "^7.21.3", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", + "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@jsdoc/salty": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", + "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@node-red/editor-api": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-2.2.3.tgz", + "integrity": "sha512-lSqxKyf5FfODGCPQoJVr3m6oHxwIWhOQ6q1fIIxkL5JGQLJ3X/F5Du/hkgNUIr5W670S+WW+rYdx109ifiz1ng==", + "dependencies": { + "@node-red/editor-client": "2.2.3", + "@node-red/util": "2.2.3", + "bcryptjs": "2.4.3", + "body-parser": "1.19.1", + "clone": "2.1.2", + "cors": "2.8.5", + "express": "4.17.2", + "express-session": "1.17.2", + "memorystore": "1.6.7", + "mime": "3.0.0", + "multer": "1.4.4", + "mustache": "4.2.0", + "oauth2orize": "1.11.1", + "passport": "0.5.2", + "passport-http-bearer": "1.0.1", + "passport-oauth2-client-password": "0.1.2", + "ws": "7.5.6" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + } + }, + "node_modules/@node-red/editor-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-2.2.3.tgz", + "integrity": "sha512-rkxx1VDE4IRiWj9u1f3yxdrt4JUP4mBtPLaLOZfPn7gPvXPJAmzA6MTzeetLWFAopxUCuH4+xsrfl5sOh1RFwQ==" + }, + "node_modules/@node-red/nodes": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-2.2.3.tgz", + "integrity": "sha512-LRaoYQgWYGT3vDfHV+xHi33w7n9KDbNe9u77mNkLAna/PHq2IVViFWtBLm4uxhrYMYs7NNr7r+3NnVyhLGQlAQ==", + "dependencies": { + "acorn": "8.7.0", + "acorn-walk": "8.2.0", + "ajv": "8.10.0", + "body-parser": "1.19.1", + "cheerio": "1.0.0-rc.10", + "content-type": "1.0.4", + "cookie": "0.4.2", + "cookie-parser": "1.4.6", + "cors": "2.8.5", + "cronosjs": "1.7.1", + "denque": "2.0.1", + "form-data": "4.0.0", + "fs-extra": "10.0.0", + "fs.notify": "0.0.4", + "got": "11.8.3", + "hash-sum": "2.0.0", + "hpagent": "0.1.2", + "https-proxy-agent": "5.0.0", + "iconv-lite": "0.6.3", + "is-utf8": "0.2.1", + "js-yaml": "3.14.1", + "media-typer": "1.1.0", + "mqtt": "4.3.5", + "multer": "1.4.4", + "mustache": "4.2.0", + "on-headers": "1.0.2", + "raw-body": "2.4.3", + "tough-cookie": "4.0.0", + "uuid": "8.3.2", + "ws": "7.5.6", + "xml2js": "0.4.23" + } + }, + "node_modules/@node-red/registry": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-2.2.3.tgz", + "integrity": "sha512-fR//QJhqDGfq91lg9onknb13xhTXMCSTQRdR1FbvhgR5g0uS4fl7ZcKTBhWkp7OzUZ+pRInuuc6JeBZTaeLKQg==", + "dependencies": { + "@node-red/util": "2.2.3", + "clone": "2.1.2", + "fs-extra": "10.0.0", + "semver": "7.3.5", + "tar": "6.1.11", + "uglify-js": "3.15.1" + } + }, + "node_modules/@node-red/runtime": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-2.2.3.tgz", + "integrity": "sha512-NQrrhpg4daIdxkqET4n20az1sV5V5OvSpfkemKZbuXuicrPy4sGZ1OZ309v4QVbky97RgVrs7iv2Z1IRBXV8og==", + "dependencies": { + "@node-red/registry": "2.2.3", + "@node-red/util": "2.2.3", + "async-mutex": "0.3.2", + "clone": "2.1.2", + "express": "4.17.2", + "fs-extra": "10.0.0", + "json-stringify-safe": "5.0.1" + } + }, + "node_modules/@node-red/util": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@node-red/util/-/util-2.2.3.tgz", + "integrity": "sha512-N/3US+wwa3mVm3jkSV/QPfVIRdQjaXyChgRPm9UAZbls6TrxJFfZxZefQt4xNKoDYQkHoFNN65Q29RtV0GfbbA==", + "dependencies": { + "fs-extra": "10.0.0", + "i18next": "21.6.11", + "json-stringify-safe": "5.0.1", + "jsonata": "1.8.6", + "lodash.clonedeep": "^4.5.0", + "moment-timezone": "0.5.34" + } + }, + "node_modules/@prantlf/jsonlint": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@prantlf/jsonlint/-/jsonlint-10.2.0.tgz", + "integrity": "sha512-KMFfds0peWLLfCu3bhClTiEN0tdj/Z86QJvn1awKHws6r+Sx6T3a44Eadz6OvqN6ZpsRkqaRpZxqddvvDAdDZQ==", + "dev": true, + "dependencies": { + "ajv": "6.10.2", + "commander": "4.0.1" + }, + "bin": { + "jsonlint": "lib/cli.js" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@prantlf/jsonlint/node_modules/ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/@prantlf/jsonlint/node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "dev": true + }, + "node_modules/@prantlf/jsonlint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", + "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.15.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", + "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/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/agent-base/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/ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escape-sequences": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", + "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ansi-escape-sequences/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "dependencies": { + "default-require-extensions": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true + }, + "node_modules/archiver": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/archiver/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/args": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz", + "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==", + "dev": true, + "dependencies": { + "camelcase": "5.0.0", + "chalk": "2.4.2", + "leven": "2.1.0", + "mri": "1.1.4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/args/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/args/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/args/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/args/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/args/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/args/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/args/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "node_modules/async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha512-2tEzliJmf5fHNafNwQLJXUasGzQCVctvsNkXmnlELHwypU0p08/rHohYvkqKIjyXpx+0rkrYv6QbhJ+UF4QkBg==", + "engines": { + "node": "*" + } + }, + "node_modules/async-mutex": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", + "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.0.tgz", + "integrity": "sha512-XV/WrPxXfzgZ8j4lcB5i6LyaXmi90yetmV/Fem0kmglGx+mpY06CiweL3YxU6wOTNLmqLUePW4G8h45nGZ/+pA==", + "deprecated": "Formdata complete broken, incorrect build size", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "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/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth-parser": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/basic-auth-parser/-/basic-auth-parser-0.0.2.tgz", + "integrity": "sha512-Y7OBvWn+JnW45JWHLY6ybYub2k9cXCMrtCyO1Hds2s6eqClqWhPnOQpgXUPjAiMHj+A8TEPIQQ1dYENnJoBOHQ==", + "dev": true + }, + "node_modules/bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ==", + "dev": true, + "dependencies": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } + }, + "node_modules/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "dependencies": { + "bytes": "3.1.1", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "dependencies": { + "bytes": "3.1.1", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body/node_modules/bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==", + "dev": true + }, + "node_modules/body/node_modules/raw-body": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==", + "dev": true, + "dependencies": { + "bytes": "1", + "string_decoder": "0.10" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/body/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==", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/busboy/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/busboy/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/busboy/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/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cache-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", + "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", + "dev": true, + "dependencies": { + "array-back": "^4.0.1", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cache-point/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "dev": true, + "dependencies": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/caching-transform/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/caching-transform/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dependencies": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", + "dependencies": { + "css-select": "^4.3.0", + "css-what": "^6.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.3.1", + "domutils": "^2.8.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", + "dev": true, + "dependencies": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "engines": { + "node": ">=0.2.5" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/cli-table/node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/collect-all": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", + "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", + "dev": true, + "dependencies": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-args/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/command-line-args/node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-tool/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commander": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.0.1.tgz", + "integrity": "sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + } + }, + "node_modules/common-sequence": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", + "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dev": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha512-n7LBL1zBzYdTpF1mx5DNcZnZn05CWIdsdvtPL4MosvqbBUK3Rq6VWEtGUuF3Y0s9/CIhMejezqlSkP6TnCJ/9g==", + "dev": true, + "dependencies": { + "walk-back": "^2.0.1" + } + }, + "node_modules/config-master/node_modules/walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha512-Nb6GvBR8UWX1D+Le+xUq0+Q1kFmRBIWVrfLnQAOmcpEzA9oAxwJ9gIr36t9TWYfzvWRvuMtjHiVsJYEkXWaTAQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/configstore/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", + "dev": true, + "dependencies": { + "date-now": "^0.1.4" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/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/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/continuable-cache": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "integrity": "sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "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/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cp-file/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cp-file/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cronosjs": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/cronosjs/-/cronosjs-1.7.1.tgz", + "integrity": "sha512-d6S6+ep7dJxsAG8OQQCdKuByI/S/AV64d9OF5mtmcykOyPu92cAkAnF3Tbc9s5oOaLQBYYQmTNvjqYRkPJ/u5Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==", + "dev": true + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "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/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha512-B0n2zDIXpzLzKeoEozorDSa1cHc1t0NjmxP0zuAxbizNU2MBqYJJKYXrrFdKuQliojXynrxgd7l4ahfg/+aA5g==", + "dev": true, + "dependencies": { + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true + }, + "node_modules/denque": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", + "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dicer/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/dicer/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/dicer/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/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dmd": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.2.0.tgz", + "integrity": "sha512-uXWxLF1H7TkUAuoHK59/h/ts5cKavm2LnhrIgJWisip4BVzPoXavlwyoprFFn2CzcahKYgvkfaebS6oxzgflkg==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "common-sequence": "^2.0.2", + "file-set": "^4.0.2", + "handlebars": "^4.7.7", + "marked": "^4.2.3", + "object-get": "^2.1.1", + "reduce-flatten": "^3.0.1", + "reduce-unique": "^2.0.1", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^5.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmd/node_modules/marked": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", + "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz", + "integrity": "sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==", + "dev": true + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "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==", + "devOptional": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", + "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", + "dev": true, + "dependencies": { + "string-template": "~0.2.1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==", + "dev": true + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", + "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.6", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-session": { + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", + "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express-session/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/express/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/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/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha512-Xhj93RXbMSq8urNCUq4p9l0P6hnySJ/7YNRhYNug0bLOuii7pKO7xQFb5mx9xZXWCar88pLPb805PvUkwrLZpQ==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-set": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", + "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", + "dev": true, + "dependencies": { + "array-back": "^5.0.0", + "glob": "^7.1.6" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/file-set/node_modules/array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/file-sync-cmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", + "integrity": "sha512-0k45oWBokCqh2MOexeYKpyqmGKG+8mQ2Wd8iawx+uWd/weWJQAZ6SoPybagdCI4xFisag8iAR77WPm4h3pTfxA==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha512-z8Nrwhi6wzxNMIbxlrTzuUW6KWuKkogZ/7OdDVq+0+kxn77KUH1nipx8iU6suqkHqc4y6n7a9A8IpmxY/pTjWg==", + "dev": true, + "dependencies": { + "glob": "~5.0.0" + }, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/findup-sync/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "dev": true, + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha512-3TOY+4TKV0Ml83PXJQY+JFQaHNV38lzQDIzzXYg1kWdBLenGgoZhAs0CKgzI31vi2pWEpQMq/Yi4bpKwCPkw7g==", + "dev": true, + "dependencies": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "node_modules/foreground-child/node_modules/cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA==", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/foreground-child/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.1.tgz", + "integrity": "sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==", + "dev": true, + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/formidable/node_modules/qs": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", + "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha512-X712jAOaWXkemQCAmWeg5rOT2i+KOpWz1Z/txk/cW0qlOu2oQ9H61vc5w3X/iyuUEfq/OyaFJ78/cZAQD1/bgA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fs.notify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fs.notify/-/fs.notify-0.0.4.tgz", + "integrity": "sha512-xnulkRf31FQwC8NsU5DEYqMTeM3jZpYsTC2hHQcHlkXTubxQHDVWkau13U/oFmFXieCkai2oKTa1MhckXk2fRQ==", + "dependencies": { + "async": "~0.1.22", + "retry": "~0.6.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "dependencies": { + "globule": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getobject": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz", + "integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globule": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", + "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", + "dev": true, + "dependencies": { + "glob": "~7.1.1", + "lodash": "^4.17.21", + "minimatch": "~3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/got": { + "version": "11.8.3", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", + "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/grunt": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.5.2.tgz", + "integrity": "sha512-XCtfaIu72OyDqK24MjWiGC9SwlkuhkS1mrULr1xzuJ2XqAFhP3ZAchZGHJeSCY6mkaOXU4F7SbmmCF7xIVoC9w==", + "dev": true, + "dependencies": { + "dateformat": "~3.0.3", + "eventemitter2": "~0.4.13", + "exit": "~0.1.2", + "findup-sync": "~0.3.0", + "glob": "~7.1.6", + "grunt-cli": "~1.4.3", + "grunt-known-options": "~2.0.0", + "grunt-legacy-log": "~3.0.0", + "grunt-legacy-util": "~2.0.1", + "iconv-lite": "~0.4.13", + "js-yaml": "~3.14.0", + "minimatch": "~3.0.4", + "mkdirp": "~1.0.4", + "nopt": "~3.0.6", + "rimraf": "~3.0.2" + }, + "bin": { + "grunt": "bin/grunt" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/grunt-chmod": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-chmod/-/grunt-chmod-1.1.1.tgz", + "integrity": "sha512-f807W/VOIhhaOW85JyeRd4DgB0RcbsGQV/4IvtcKctOWGvPJns4AqN7xW73PG9+RwDnSGxApS+6Xov5L2LeNXg==", + "dev": true, + "dependencies": { + "shelljs": "^0.5.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/grunt-cli": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", + "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", + "dev": true, + "dependencies": { + "grunt-known-options": "~2.0.0", + "interpret": "~1.1.0", + "liftup": "~3.0.1", + "nopt": "~4.0.1", + "v8flags": "~3.2.0" + }, + "bin": { + "grunt": "bin/grunt" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-cli/node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/grunt-concurrent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-concurrent/-/grunt-concurrent-3.0.0.tgz", + "integrity": "sha512-AgXtjUJESHEGeGX8neL3nmXBTHSj1QC48ABQ3ng2/vjuSBpDD8gKcVHSlXP71pFkIR8TQHf+eomOx6OSYSgfrA==", + "dev": true, + "dependencies": { + "arrify": "^2.0.1", + "async": "^3.1.0", + "indent-string": "^4.0.0", + "pad-stream": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "grunt": ">=1" + } + }, + "node_modules/grunt-concurrent/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/grunt-contrib-clean": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-2.0.1.tgz", + "integrity": "sha512-uRvnXfhiZt8akb/ZRDHJpQQtkkVkqc/opWO4Po/9ehC2hPxgptB9S6JHDC/Nxswo4CJSM0iFPT/Iym3cEMWzKA==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "rimraf": "^2.6.2" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "grunt": ">=0.4.5" + } + }, + "node_modules/grunt-contrib-clean/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/grunt-contrib-clean/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/grunt-contrib-compress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-2.0.0.tgz", + "integrity": "sha512-r/dAGx4qG+rmBFF4lb/hTktW2huGMGxkSLf9msh3PPtq0+cdQRQerZJ30UKevX3BLQsohwLzO0p1z/LrH6aKXQ==", + "dev": true, + "dependencies": { + "adm-zip": "^0.5.1", + "archiver": "^5.1.0", + "chalk": "^4.1.0", + "lodash": "^4.17.20", + "pretty-bytes": "^5.4.1", + "stream-buffers": "^3.0.2" + }, + "engines": { + "node": ">=10.16" + } + }, + "node_modules/grunt-contrib-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz", + "integrity": "sha512-QdTmcxe8aim2Z0dFeuSJ+f7fHIeY7PZaTMZxgvosjXwyMhpy2GUR5WHkr12lksHfZVE80v2wUwqF56wyfPUwoQ==", + "dev": true, + "dependencies": { + "chalk": "^1.0.0", + "source-map": "^0.5.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "grunt": ">=0.4.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-concat/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-copy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", + "integrity": "sha512-gFRFUB0ZbLcjKb67Magz1yOHGBkyU6uL29hiEW1tdQ9gQt72NuMKIy/kS6dsCbV0cZ0maNCb0s6y+uT1FKU7jA==", + "dev": true, + "dependencies": { + "chalk": "^1.1.1", + "file-sync-cmp": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-copy/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-jshint": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-3.1.1.tgz", + "integrity": "sha512-EwMY6L91FqTcMlZTVoDeeq/EZL+7MoFyo1rxIea9sxyv73geVggeE37jcUhNbu5hLbxHE82CGIUqitHuR2/q+g==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "hooker": "^0.2.3", + "jshint": "~2.13.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-contrib-uglify": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-5.0.1.tgz", + "integrity": "sha512-T/aXZ4WIpAtoswZqb6HROKg7uq9QbKwl+lUuOwK4eoFj3tFv9/a/oMyd3/qvetV29Pbf8P1YYda1gDwZppr60A==", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "maxmin": "^2.1.0", + "uglify-js": "^3.13.3", + "uri-path": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/grunt-contrib-uglify/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-uglify/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/grunt-contrib-watch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", + "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", + "dev": true, + "dependencies": { + "async": "^2.6.0", + "gaze": "^1.1.0", + "lodash": "^4.17.10", + "tiny-lr": "^1.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-watch/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/grunt-jsdoc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz", + "integrity": "sha512-S0zxU0wDewRu7z+vijEItOWe/UttxWVmvz0qz2ZVcAYR2GpXjsiski2CAVN0b18t2qeVLdmxZkJaEWCOsKzcAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1", + "jsdoc": "^3.6.3" + }, + "bin": { + "grunt-jsdoc": "bin/grunt-jsdoc" + }, + "engines": { + "node": ">= 8.12.0" + } + }, + "node_modules/grunt-jsdoc-to-markdown": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/grunt-jsdoc-to-markdown/-/grunt-jsdoc-to-markdown-6.0.0.tgz", + "integrity": "sha512-vvanKUErp6CHl4MuLQ9vwJewpMu8Fi7z09lr4OwMLr+GBu3nG5lRNZuu5mkWY8qv1aU8WkX97/rJaVs3A1Wx8g==", + "dev": true, + "dependencies": { + "jsdoc-to-markdown": "^7.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "grunt": ">=1.3.0" + } + }, + "node_modules/grunt-jsonlint": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/grunt-jsonlint/-/grunt-jsonlint-2.1.3.tgz", + "integrity": "sha512-h04qC969LIyhsJaASeJ/hDnnKnsnSNZKqjYHra6cc/WQzrfMZinQPdr11FhU4T8OzAq6ecMX5QauYiJkbjUV/Q==", + "dev": true, + "dependencies": { + "@prantlf/jsonlint": "10.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/grunt-known-options": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", + "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-legacy-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", + "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", + "dev": true, + "dependencies": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.19" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/grunt-legacy-log-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", + "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", + "dev": true, + "dependencies": { + "chalk": "~4.1.0", + "lodash": "~4.17.19" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-legacy-util": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", + "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", + "dev": true, + "dependencies": { + "async": "~3.2.0", + "exit": "~0.1.2", + "getobject": "~1.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.21", + "underscore.string": "~3.3.5", + "which": "~2.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-legacy-util/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/grunt-mkdir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-mkdir/-/grunt-mkdir-1.1.0.tgz", + "integrity": "sha512-FRE17OYVveNbVJFX8GPGa5bzH2ZiAdBx3q0Kwk2Dg6l+TzLGaTdufUxiUWUbS2MERFacnmXZwDDOR5ZbYW0o+Q==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + }, + "peerDependencies": { + "grunt": ">=0.4.0" + } + }, + "node_modules/grunt-npm-command": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/grunt-npm-command/-/grunt-npm-command-0.1.2.tgz", + "integrity": "sha512-QsGLL8Pp+tzeIkCqohIbOtVopOhINErRVpxKY+SnvSEE3BXOKKSanlIh9cd1mliajO57sXG2ZC4R8L3v2NSPTQ==", + "dev": true, + "peerDependencies": { + "grunt": ">=0.4.0" + } + }, + "node_modules/grunt-sass": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.1.0.tgz", + "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", + "dev": true, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "grunt": ">=1" + } + }, + "node_modules/grunt-simple-mocha": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/grunt-simple-mocha/-/grunt-simple-mocha-0.4.1.tgz", + "integrity": "sha512-EibTuZVvyLd9v/9An+5sL+XLoArs1QkFSTUcOG/AbBzeCYemZppcO9YSEspWUwU/T/NNtAyzB+x7B6zAmKQqkA==", + "dev": true, + "dependencies": { + "mocha": "*" + }, + "bin": { + "grunt-simple-mocha": "bin/grunt-simple-mocha" + }, + "engines": { + "node": "*" + } + }, + "node_modules/grunt-simple-nyc": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/grunt-simple-nyc/-/grunt-simple-nyc-3.0.1.tgz", + "integrity": "sha512-/YLY+jNI6gBuVO3xu07zwvDN+orTAFS50W00yb/2ncvc2PFO4pR+oU7TyiHhe8a6O3KuQDHsyCE0iE+rqJagQg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15", + "nyc": "^14.1.0", + "simple-cli": "^5.0.3" + } + }, + "node_modules/grunt/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt/node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/gzip-size": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", + "integrity": "sha512-6s8trQiK+OMzSaCSVXX+iqIcLV9tC+E73jrJrJTyS4h/AJhlxHvzFKqM1YLDJWRGgHX8uLkBeXkA0njNj39L4w==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.1" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + }, + "node_modules/hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha512-w0Kz8lJFBoyaurBiNrIvxPqr/gJ6fOfSkpAPOepN3oECqGJag37xPbOv57izi/KP8auHgNYxn5fXtAb+1LsJ6w==", + "dev": true, + "dependencies": { + "is-stream": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", + "dependencies": { + "glob": "^7.1.6", + "readable-stream": "^3.6.0" + } + }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha512-t+UerCsQviSymAInD01Pw+Dn/usmz1sRO+3Zk1+lx8eg+WKpD2ulcwWqHHL0+aseRBr+3+vIhiG1K1JTwaIcTA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/hpagent": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-0.1.2.tgz", + "integrity": "sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/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/https-proxy-agent/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/i18next": { + "version": "21.6.11", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.11.tgz", + "integrity": "sha512-tJ2+o0lVO+fhi8bPkCpBAeY1SgkqmQm5NzgPWCQssBrywJw98/o+Kombhty5nxQOpHtvMmsxcOopczUiH6bJxQ==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/i18next-http-backend": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.3.2.tgz", + "integrity": "sha512-SfcoUmsSWnc2LYsDsCq5TCg18cxJXvXymX9N37V+qqMKQY8Gf0rWkjOnRd20sMK633Dq4NF9tvqPbOiFJ49Kbw==", + "dev": true, + "dependencies": { + "cross-fetch": "3.1.5" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/immutable": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", + "dev": true + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha512-CLM8SNMDu7C5psFCn6Wg/tgpj/bKAg7hc2gWqcuR9OD5Ft9PhBpIu8PLicPeis+xDd6YX2ncI8MCA64I9tftIA==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "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/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "dev": true, + "dependencies": { + "append-transform": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/istanbul-lib-source-maps/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jquery-i18next": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jquery-i18next/-/jquery-i18next-1.2.1.tgz", + "integrity": "sha512-UNcw3rgxoKjGEg4w23FEn2h3OlPJU7rPzsgDuXDBZktIzeiVbJohs9Cv9hj8oP8KNfBRKOoErL/OVxg2FaAR4g==", + "dev": true + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", + "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.4", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc-api": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.2.0.tgz", + "integrity": "sha512-93YDnlm/OYTlLOFeNs4qAv0RBCJ0kGj67xQaWy8wrbk97Rw1EySitoOTHsTHXPEs3uyx2IStPKGrbE7LTnZXbA==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "collect-all": "^1.0.4", + "file-set": "^4.0.2", + "fs-then-native": "^2.0.0", + "jsdoc": "^4.0.0", + "object-to-spawn-args": "^2.0.1", + "temp-path": "^1.0.0", + "walk-back": "^5.1.0" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/jsdoc-api/node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc-nr-template": { + "version": "1.0.0", + "resolved": "git+ssh://git@github.com/node-red/jsdoc-nr-template.git#3c7c8f96d585c7c5918a2e63519310e1297e162d", + "dev": true + }, + "node_modules/jsdoc-parse": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.2.0.tgz", + "integrity": "sha512-Afu1fQBEb7QHt6QWX/6eUWvYHJofB90Fjx7FuJYF7mnG9z5BkAIpms1wsnvYLytfmqpEENHs/fax9p8gvMj7dw==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "reduce-extract": "^1.0.0", + "sort-array": "^4.1.5", + "test-value": "^3.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdoc-to-markdown": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", + "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^6.1.0", + "jsdoc-api": "^7.1.1", + "jsdoc-parse": "^6.1.0", + "walk-back": "^5.1.0" + }, + "bin": { + "jsdoc2md": "bin/cli.js" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jshint": { + "version": "2.13.6", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.6.tgz", + "integrity": "sha512-IVdB4G0NTTeQZrBoM8C5JFVLjV2KtZ9APgybDA1MK73xb09qFs0jCXyQLnCOp1cSZZZbvhq/6mfXHUTaDkffuQ==", + "dev": true, + "dependencies": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "strip-json-comments": "1.0.x" + }, + "bin": { + "jshint": "bin/jshint" + } + }, + "node_modules/jshint/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/jshint/node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/jshint/node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jshint/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "node_modules/jshint/node_modules/domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", + "dev": true, + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/jshint/node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/jshint/node_modules/entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==", + "dev": true + }, + "node_modules/jshint/node_modules/htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", + "dev": true, + "dependencies": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "node_modules/jshint/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==", + "dev": true + }, + "node_modules/jshint/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==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/jshint/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==", + "dev": true + }, + "node_modules/jshint/node_modules/strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", + "dev": true, + "bin": { + "strip-json-comments": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/jsonata": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-1.8.6.tgz", + "integrity": "sha512-ZH2TPYdNP2JecOl/HvrH47Xc+9imibEMQ4YqKy/F/FrM+2a6vfbGxeCX23dB9Fr6uvGwv+ghf1KxWB3iZk09wA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "node_modules/key-list": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/key-list/-/key-list-0.1.4.tgz", + "integrity": "sha512-DMGLZAmEoKRUHPlc772EW0i92P/WY12/oWYc2pQZb5MVGOSjYmF0BEQXbOLjbou1+/PqZ+CivwfyjaUwmyl4CQ==", + "dev": true + }, + "node_modules/keyv": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/liftup": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", + "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", + "dev": true, + "dependencies": { + "extend": "^3.0.2", + "findup-sync": "^4.0.0", + "fined": "^1.2.0", + "flagged-respawn": "^1.0.1", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.1", + "rechoir": "^0.7.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/liftup/node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/livereload-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", + "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", + "dev": true + }, + "node_modules/lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==", + "dev": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "dev": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "devOptional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "devOptional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/maxmin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", + "integrity": "sha512-NWlApBjW9az9qRPaeg7CX4sQBWwytqz32bIEo1PW9pRW+kBP9KLRfJO3UC+TV31EcQZEUq7eMzikC7zt3zPJcw==", + "dev": true, + "dependencies": { + "chalk": "^1.0.0", + "figures": "^1.0.1", + "gzip-size": "^3.0.0", + "pretty-bytes": "^3.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/maxmin/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/maxmin/node_modules/pretty-bytes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", + "integrity": "sha512-eb7ZAeUTgfh294cElcu51w+OTRp/6ItW758LjwJSK72LDevcuJn0P4eD71PLMDGPwwatXmAmYHTkzvpKlJE3ow==", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/maxmin/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/memorystore": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/memorystore/-/memorystore-1.6.7.tgz", + "integrity": "sha512-OZnmNY/NDrKohPQ+hxp0muBcBKrzKNtHr55DbqSx9hLsYVNnomSAMRAtI7R64t3gf3ID7tHQA7mG4oL3Hu9hdw==", + "dependencies": { + "debug": "^4.3.0", + "lru-cache": "^4.0.3" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/memorystore/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/memorystore/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/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minami": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/minami/-/minami-1.2.3.tgz", + "integrity": "sha512-3f2QqqbUC1usVux0FkQMFYB73yd9JIxmHSn1dWQacizL6hOUaNu6mA3KxZ9SfiCc4qgcgq+5XP59+hP7URa1Dw==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", + "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", + "dev": true + }, + "node_modules/mocha": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.0.tgz", + "integrity": "sha512-kNn7E8g2SzVcq0a77dkphPsDSN7P+iYkqE0ZsGCYWRsoiKjOt+NvXfaagik8vuDa6W5Zw3qxe8Jfpt5qKf+6/Q==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.2.0", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.34", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", + "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.5.tgz", + "integrity": "sha512-l29WGHAc0EayK1cjb6moozc+rlgK6YRCPbP3zB1CrJw84Bjk4kG9EJCXojdn4r29lA80SCqxRKq1QJ87+Xevng==", + "dependencies": { + "commist": "^1.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.1.1", + "duplexify": "^4.1.1", + "help-me": "^3.0.0", + "inherits": "^2.0.3", + "lru-cache": "^6.0.0", + "minimist": "^1.2.5", + "mqtt-packet": "^6.8.0", + "number-allocator": "^1.0.9", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^3.1.0", + "ws": "^7.5.5", + "xtend": "^4.0.2" + }, + "bin": { + "mqtt": "bin/mqtt.js", + "mqtt_pub": "bin/pub.js", + "mqtt_sub": "bin/sub.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", + "dependencies": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt-packet/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/mqtt-packet/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/mqtt/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/mqtt/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mqtt/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/mqtt/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mri": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", + "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/multer/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/multer/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/multer/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/nanoid": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nested-error-stacks": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", + "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==", + "dev": true + }, + "node_modules/nise": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", + "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^10.0.2", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", + "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0" + } + }, + "node_modules/nise/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==", + "dev": true + }, + "node_modules/nise/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-red": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/node-red/-/node-red-2.2.3.tgz", + "integrity": "sha512-sfOsWONOF5TyNApXv6AkLzwfxq+C+3lyUrXRvyuQxWt1dSGvfg417dbEx4WW0kxwREGZ47TKtLejnoTPnV5adQ==", + "dependencies": { + "@node-red/editor-api": "2.2.3", + "@node-red/nodes": "2.2.3", + "@node-red/runtime": "2.2.3", + "@node-red/util": "2.2.3", + "basic-auth": "2.0.1", + "bcryptjs": "2.4.3", + "express": "4.17.2", + "fs-extra": "10.0.0", + "node-red-admin": "^2.2.3", + "nopt": "5.0.0", + "semver": "7.3.5" + }, + "bin": { + "node-red": "red.js", + "node-red-pi": "bin/node-red-pi" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + } + }, + "node_modules/node-red-admin": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/node-red-admin/-/node-red-admin-2.2.4.tgz", + "integrity": "sha512-DlJpMFopqBNj10k5rGGI9ZNBi+whAIS+IHrSZH1xllfuJKZxQBZgR+o+rJeufDyc0OBRgHRqmX776HrBrlDtMA==", + "dependencies": { + "ansi-colors": "^4.1.1", + "axios": "0.27.0", + "bcryptjs": "^2.4.3", + "cli-table": "^0.3.11", + "enquirer": "^2.3.6", + "minimist": "^1.2.6", + "mustache": "^4.2.0", + "read": "^1.0.7" + }, + "bin": { + "node-red-admin": "node-red-admin.js" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + } + }, + "node_modules/node-red-contrib-pythonshell": { + "version": "1.5.4", + "resolved": "git+ssh://git@github.com/namgk/node-red-contrib-pythonshell.git#6bcc7df0003600bde8d688ece9c8d20caa00992f", + "license": "ISC" + }, + "node_modules/node-red-node-test-helper": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/node-red-node-test-helper/-/node-red-node-test-helper-0.2.7.tgz", + "integrity": "sha512-OanSQ1hrsigHVtMjL/cuhtjxhTdRBXxd3IALJC9eg0WOHRF75ZI7RYhFWqqOsvQ++BwmNj8ki1S49D8cZyZTWA==", + "dev": true, + "dependencies": { + "body-parser": "1.19.0", + "express": "4.17.1", + "read-pkg-up": "7.0.1", + "semver": "7.3.4", + "should": "^13.2.3", + "should-sinon": "0.0.6", + "sinon": "9.2.4", + "stoppable": "1.1.0", + "supertest": "4.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/node-red-node-test-helper/node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/node-red-node-test-helper/node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "dev": true, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/node-red-node-test-helper/node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/node-red-node-test-helper/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-red-node-test-helper/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/node-red-node-test-helper/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/node-red-node-test-helper/node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/nise/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==", + "dev": true + }, + "node_modules/node-red-node-test-helper/node_modules/nise/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/node-red-node-test-helper/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-red-node-test-helper/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/node-red-node-test-helper/node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-red-node-test-helper/node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "node_modules/node-red-node-test-helper/node_modules/sinon": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/node-red-node-test-helper/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", + "dev": true, + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/superagent/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/node-red-node-test-helper/node_modules/supertest": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", + "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^3.8.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-red-node-test-helper/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/node-red-node-test-helper/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/nodemon": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", + "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5", + "update-notifier": "^5.1.0" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nodemon/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/number-allocator/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/number-allocator/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/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/nyc/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/nyc/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/nyc/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/nyc/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/nyc/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nyc/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/nyc/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/oauth2orize": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/oauth2orize/-/oauth2orize-1.11.1.tgz", + "integrity": "sha512-9dSx/Gwm0J2Rvj4RH9+h7iXVnRXZ6biwWRgb2dCeQhCosODS0nYdM9I/G7BUGsjbgn0pHjGcn1zcCRtzj2SlRA==", + "dependencies": { + "debug": "2.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-get": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", + "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", + "dev": true + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-to-spawn-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", + "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "dev": true, + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opted": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/opted/-/opted-1.0.2.tgz", + "integrity": "sha512-uEvunmdmKcSFiBSmnY2E9E/HbghO5yc1J0yNmq7T18YkAJeWNlo33e6VYKkRK4eudVrpvvlLdemAeAuL6rZxjQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/package-json/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/package-json/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/package-json/node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/got/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "node_modules/package-json/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/package-json/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/package-json/node_modules/responselike/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/pad-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pad-stream/-/pad-stream-2.0.0.tgz", + "integrity": "sha512-3QeQw19K48BQzUGZ9dEf/slX5Jbfy5ZeBTma2XICketO7kFNK7omF00riVcecOKN+DSiJZcK2em1eYKaVOeXKg==", + "dev": true, + "dependencies": { + "pumpify": "^1.3.3", + "split2": "^2.1.1", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pad-stream/node_modules/split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dev": true, + "dependencies": { + "through2": "^2.0.2" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.2.tgz", + "integrity": "sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-http-bearer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", + "integrity": "sha512-SELQM+dOTuMigr9yu8Wo4Fm3ciFfkMq5h/ZQ8ffi4ELgZrX1xh9PlglqZdcUZ1upzJD/whVyt+YWF62s3U6Ipw==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2-client-password": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/passport-oauth2-client-password/-/passport-oauth2-client-password-0.1.2.tgz", + "integrity": "sha512-GHQH4UtaEZvCLulAxGKHYoSsPRoPRmGsdmaZtMh5nmz80yMLQbdMA9Bg2sp4/UW3PIxJH/143hVjPTiXaNngTQ==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "dev": true, + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/proxy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/proxy/-/proxy-1.0.2.tgz", + "integrity": "sha512-KNac2ueWRpjbUh77OAFPZuNdfEqNynm9DD4xHT14CccGpW8wKZwEkN0yjlb7X9G9Z9F55N0Q+1z+WfgAhwYdzQ==", + "dev": true, + "dependencies": { + "args": "5.0.1", + "basic-auth-parser": "0.0.2", + "debug": "^4.1.1" + }, + "bin": { + "proxy": "bin/proxy.js" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/proxy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/pumpify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz", + "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", + "dev": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha512-QF8vjWx3wnRSL5uFMyCjDeDc5EBMiryoT9tz94VvgjKfzecHAVnqmXAwQDcr7X4JmLc2cjkjFGCVzhMqDjgR9g==", + "dev": true, + "dependencies": { + "test-value": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-extract/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-extract/node_modules/test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha512-wrsbRo7qP+2Je8x8DsK8ovCGyxe3sYfQwOraIY/09A2gFXU9DYKiTF14W4ki/01AEh56kMzAmlj9CaHGDDUBJA==", + "dev": true, + "dependencies": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-flatten": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", + "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reduce-unique": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", + "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha512-zQv5y/cf85sxvdrKPlfcRzlDn/OqKFThNimYmsS3flmkioKvkUGn2Qg9cJVoQiEvdxFGLE0MQER/9fZ9sUqdxg==", + "dev": true, + "dependencies": { + "test-value": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-without/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-without/node_modules/test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w==", + "dev": true, + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==" + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.6.1.tgz", + "integrity": "sha512-txv1qsctZq8ei9J/uCXgaKKFPjlBB0H2hvtnzw9rjKWFNUFtKh59WprXxpAeAey3/QeWwHdxMFqStPaOAgy+dA==", + "engines": { + "node": "*" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "devOptional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/safe-json-parse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "integrity": "sha512-o0JmTu17WGUaUOHa1l0FPGXKBfijbxK6qoHzlkihsDXxzBHvJcA7zgviKR92Xs841rX9pK16unfphLq0/KqX7A==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sass": { + "version": "1.49.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.7.tgz", + "integrity": "sha512-13dml55EMIR2rS4d/RDHHP0sXMY3+30e1TKsyXaSz3iLWVoDWEoboY8WzJd5JMnxrRHffKO3wq2mpJ0jxRJiEQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "devOptional": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", + "integrity": "sha512-C2FisSSW8S6TIYHHiMHN0NqzdjWfTekdMpA2FJTbRWnQMLO1RRIXEB9eVZYOlofYmjZA7fY3ChoFu09MeI3wlQ==", + "dev": true, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-sinon": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/should-sinon/-/should-sinon-0.0.6.tgz", + "integrity": "sha512-ScBOH5uW5QVFaONmUnIXANSR6z5B8IKzEmBP3HE5sPOCDuZ88oTMdUdnKoCVQdLcCIrRrhRLPS5YT+7H40a04g==", + "dev": true, + "peerDependencies": { + "should": ">= 8.x" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "devOptional": true + }, + "node_modules/simple-cli": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/simple-cli/-/simple-cli-5.0.5.tgz", + "integrity": "sha512-Er2FhsIayL/sktxg6fOCdNQJBTXhlf/fswNFsdmks88xsHzQ/IXGwxYgSSKeXBq4yqn83/iD4Sg8yjagwysUgw==", + "dev": true, + "dependencies": { + "async": "^3.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^7.0.0", + "key-list": "^0.1.4", + "lodash": "^4.17.15", + "opted": "^1.0.0" + } + }, + "node_modules/simple-cli/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-cli/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/simple-cli/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-cli/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/simple-cli/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/simple-cli/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/simple-cli/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-cli/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sinon": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", + "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sort-array": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.5.tgz", + "integrity": "sha512-Ya4peoS1fgFN42RN1REk2FgdNOeLIEMKFGJvs7VTP3OklF8+kl2SkpVliZ4tk/PurWsrWRsdNdU+tgyOBkB9sA==", + "dev": true, + "dependencies": { + "array-back": "^5.0.0", + "typical": "^6.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sort-array/node_modules/array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/sort-array/node_modules/typical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", + "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-wrap": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "dev": true, + "dependencies": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "node_modules/spawn-wrap/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/spawn-wrap/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/spawn-wrap/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true, + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/stream-buffers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", + "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha512-68Kl+79cE0RGKemKkhxTSg8+6AGrqBt+cbZAXevg2iJ6Y3zX4JhA/sZeGzLpxW9cXhmqAcE7KnJCisUmIUfnFQ==", + "dev": true, + "dependencies": { + "array-back": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-connect/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/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/string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==", + "dev": true + }, + "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==", + "devOptional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superagent": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", + "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.3", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.0.1", + "methods": "^1.1.2", + "mime": "^2.5.0", + "qs": "^6.10.3", + "readable-stream": "^3.6.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/superagent/node_modules/qs": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", + "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/superagent/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/superagent/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/supertest": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.2.2.tgz", + "integrity": "sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^7.1.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", + "dev": true + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha512-TvmyH7kC6ZVTYkqCODjJIbgvu0FKiwQpZ4D1aknE7xpcDf/qEOB8KZEK5ef2pfbVoiBhNWs3yx4y+ESMtNYmlg==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "dependencies": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/test-exclude/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/test-exclude/node_modules/read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/test-value/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tiny-lr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", + "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "dev": true, + "dependencies": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + } + }, + "node_modules/tiny-lr/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/tiny-lr/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/touch/node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/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/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "devOptional": true + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg==", + "dev": true + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz", + "integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "dev": true + }, + "node_modules/underscore.string": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", + "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", + "dev": true, + "dependencies": { + "sprintf-js": "^1.1.1", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/underscore.string/node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", + "integrity": "sha512-8pMuAn4KacYdGMkFaoQARicp4HSw24/DHOVKWqVRJ8LhhAwPPFpdGvdL9184JVmUwe7vz7Z9n6IqI6t5n2ELdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walk-back": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", + "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "devOptional": true + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "devOptional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "dependencies": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", + "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "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" + } + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/Tunghai-CS-project-main/kubeflow/examples/package.json b/Tunghai-CS-project-main/kubeflow/examples/package.json new file mode 100644 index 000000000..bd277eebc --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/package.json @@ -0,0 +1,127 @@ +{ + "name": "node-red", + "version": "2.2.3", + "description": "Low-code programming for event-driven applications", + "homepage": "http://nodered.org", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/node-red/node-red.git" + }, + "private": "true", + "scripts": { + "start": "node $NODE_OPTIONS node_modules/node-red/red.js", + "test": "grunt", + "build": "grunt build", + "dev": "grunt dev", + "build-dev": "grunt build-dev", + "docs": "grunt docs" + }, + "contributors": [ + { + "name": "Nick O'Leary" + }, + { + "name": "Dave Conway-Jones" + } + ], + "dependencies": { + "acorn": "8.7.0", + "acorn-walk": "8.2.0", + "ajv": "8.10.0", + "async-mutex": "0.3.2", + "basic-auth": "2.0.1", + "bcryptjs": "2.4.3", + "body-parser": "1.19.1", + "cheerio": "1.0.0-rc.10", + "clone": "2.1.2", + "content-type": "1.0.4", + "cookie": "0.4.2", + "cookie-parser": "1.4.6", + "cors": "2.8.5", + "cronosjs": "1.7.1", + "denque": "2.0.1", + "express": "4.17.2", + "express-session": "1.17.2", + "form-data": "4.0.0", + "fs-extra": "10.0.0", + "fs.notify": "0.0.4", + "got": "11.8.3", + "hash-sum": "2.0.0", + "hpagent": "0.1.2", + "https-proxy-agent": "5.0.0", + "i18next": "21.6.11", + "iconv-lite": "0.6.3", + "is-utf8": "0.2.1", + "js-yaml": "3.14.1", + "json-stringify-safe": "5.0.1", + "jsonata": "1.8.6", + "lodash.clonedeep": "^4.5.0", + "media-typer": "1.1.0", + "memorystore": "1.6.7", + "mime": "3.0.0", + "moment-timezone": "0.5.34", + "mqtt": "4.3.5", + "multer": "1.4.4", + "mustache": "4.2.0", + "node-red": "2.2.3", + "node-red-admin": "^2.2.3", + "node-red-contrib-pythonshell": "github:namgk/node-red-contrib-pythonshell", + "nopt": "5.0.0", + "oauth2orize": "1.11.1", + "on-headers": "1.0.2", + "passport": "0.5.2", + "passport-http-bearer": "1.0.1", + "passport-oauth2-client-password": "0.1.2", + "raw-body": "2.4.3", + "semver": "7.3.5", + "tar": "6.1.11", + "tough-cookie": "4.0.0", + "uglify-js": "3.15.1", + "uuid": "8.3.2", + "ws": "7.5.6", + "xml2js": "0.4.23" + }, + "optionalDependencies": { + "bcrypt": "5.0.1" + }, + "devDependencies": { + "dompurify": "2.3.6", + "grunt": "1.5.2", + "grunt-chmod": "~1.1.1", + "grunt-cli": "~1.4.3", + "grunt-concurrent": "3.0.0", + "grunt-contrib-clean": "~2.0.0", + "grunt-contrib-compress": "2.0.0", + "grunt-contrib-concat": "~1.0.1", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-jshint": "3.1.1", + "grunt-contrib-uglify": "5.0.1", + "grunt-contrib-watch": "~1.1.0", + "grunt-jsdoc": "2.4.1", + "grunt-jsdoc-to-markdown": "6.0.0", + "grunt-jsonlint": "2.1.3", + "grunt-mkdir": "~1.1.0", + "grunt-npm-command": "~0.1.2", + "grunt-sass": "~3.1.0", + "grunt-simple-mocha": "~0.4.1", + "grunt-simple-nyc": "^3.0.1", + "i18next-http-backend": "1.3.2", + "jquery-i18next": "1.2.1", + "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", + "marked": "4.0.12", + "minami": "1.2.3", + "mocha": "9.2.0", + "node-red-node-test-helper": "^0.2.7", + "nodemon": "2.0.15", + "proxy": "^1.0.2", + "sass": "1.49.7", + "should": "13.2.3", + "sinon": "11.1.2", + "stoppable": "^1.1.0", + "supertest": "6.2.2" + }, + "engines": { + "node": ">=12" + } +} diff --git a/Tunghai-CS-project-main/kubeflow/examples/run.sh b/Tunghai-CS-project-main/kubeflow/examples/run.sh new file mode 100644 index 000000000..daca187e0 --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/run.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +target=$1 + +if [ "$#" -eq 1 ] +then + USERDIR=/data/$target +else + USERDIR=/data/0.helloworld +fi + +echo "run with userdir=$USERDIR" + +USERDIR=$USERDIR docker compose up +#USERDIR=$USERDIR docker compose convert diff --git a/Tunghai-CS-project-main/kubeflow/examples/scripts/entrypoint.sh b/Tunghai-CS-project-main/kubeflow/examples/scripts/entrypoint.sh new file mode 100644 index 000000000..705054c0a --- /dev/null +++ b/Tunghai-CS-project-main/kubeflow/examples/scripts/entrypoint.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +trap stop SIGINT SIGTERM + +function stop() { + kill $CHILD_PID + wait $CHILD_PID +} + +/usr/local/bin/node $NODE_OPTIONS node_modules/node-red/red.js --userDir $USERDIR & + +CHILD_PID="$!" + +wait "${CHILD_PID}"