diff --git a/.gitignore b/.gitignore
index f32e31a..04bb47d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.idea/
.DS_Store
+/deploy
diff --git a/.htpasswd b/.htpasswd
new file mode 100644
index 0000000..ee4e601
--- /dev/null
+++ b/.htpasswd
@@ -0,0 +1 @@
+admin:$apr1$zpnuu5ho$Swc8jhnhlHV.qqgoaLGdO1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba5d699..671d286 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,121 +2,131 @@
All notable changes to this project will be documented in this file.
+## [1.0.0] – 2023-05-11
+
+- Many changes to make the deployment process easier to understand.
+- Added `https://your.domain/arangodb` and `https://your.domain/metrics` routes.
+- Basic authentication is required to access the arangodb web interface at https:`//your.domain/arangodb`.
+- Removed kafka schema registry, remove connect-cli binary.
+- Arangodb version updated to arangodb:3.10.5
+- Message size in Kafka increased up to 4Mb.
+
## [0.2.0] – 2022-10-18
## New
-- Node console added
-- ton-q-server updated to 0.54.0 version (ext_in_msg_max_size increased to 64 kb)
+- Node console added
+- ton-q-server updated to 0.54.0 version (ext_in_msg_max_size increased to 64 kb)
### Improvements
-- updated ton-labs-node from `c5ee530c54199e81e2ca241a17ec23be7290229a` to `befb1ba4d91733ee2c14fa3cf4ebe8047b279e92`
+- updated ton-labs-node from `c5ee530c54199e81e2ca241a17ec23be7290229a` to `befb1ba4d91733ee2c14fa3cf4ebe8047b279e92`
## [0.1.9] – 2022-08-12
### Improvements
-- updated ton-labs-node from `5438eaab4db17c0c78869debf3e936078d9d7150` to `c5ee530c54199e81e2ca241a17ec23be7290229a`
+- updated ton-labs-node from `5438eaab4db17c0c78869debf3e936078d9d7150` to `c5ee530c54199e81e2ca241a17ec23be7290229a`
### Fixed
-- fixed IP address detection issue
+
+- fixed IP address detection issue
## [0.1.8] – 2022-06-27
### Improvements
-- updated ton-q-server from `0.52.0` to `0.52.1`
-- updated ton-labs-node from `5c3951a4de03833a49079d1c07ad5a05798df169` to `5438eaab4db17c0c78869debf3e936078d9d7150`
+- updated ton-q-server from `0.52.0` to `0.52.1`
+- updated ton-labs-node from `5c3951a4de03833a49079d1c07ad5a05798df169` to `5438eaab4db17c0c78869debf3e936078d9d7150`
### Fixed
-- fixed `master.shard_hashes.shard` in master blocks in one-shard scenario
+
+- fixed `master.shard_hashes.shard` in master blocks in one-shard scenario
## [0.1.7] – 2022-06-27
### New
-- support `query { blockchain { .. } }` GraphQL API queries in Evernode DApp Server
+- support `query { blockchain { .. } }` GraphQL API queries in Evernode DApp Server
### Improvements
-- updated ton-q-server from `0.48.1` to `0.52.0`
-- updated ton-labs-node from `49a724639a175752f44bcda65d907f2ca3ad97aa` to `5c3951a4de03833a49079d1c07ad5a05798df169`
-- updated kafka-connect-arangodb to custom solution with additional `overwritemode` parameter
-- changed arangodb-messages-sink configuration to update messages instead of replacing
-- added 20 new indexes to arangodb
+- updated ton-q-server from `0.48.1` to `0.52.0`
+- updated ton-labs-node from `49a724639a175752f44bcda65d907f2ca3ad97aa` to `5c3951a4de03833a49079d1c07ad5a05798df169`
+- updated kafka-connect-arangodb to custom solution with additional `overwritemode` parameter
+- changed arangodb-messages-sink configuration to update messages instead of replacing
+- added 20 new indexes to arangodb
## [0.1.6] – 2022-03-29
### Improvements
-- ton-labs-node dependency is fixed to `49a724639a175752f44bcda65d907f2ca3ad97aa`
-- Disabled big_messages_storage
+- ton-labs-node dependency is fixed to `49a724639a175752f44bcda65d907f2ca3ad97aa`
+- Disabled big_messages_storage
## [0.1.5] – 2022-03-23
### New
-- Support of new Account format for new TVM instruction INITCODEHASH
-- Account.init_code_hash field added to API
+- Support of new Account format for new TVM instruction INITCODEHASH
+- Account.init_code_hash field added to API
### Improvements
-- ton-labs-node dependency is fixed to `3020fa75d73de06433fb162e64dcc830acdf9d6e`
-- updated Q-Server to [`0.48.1`](https://github.com/tonlabs/ton-q-server/blob/master/CHANGELOG.md#0481---2022-03-16)
+
+- ton-labs-node dependency is fixed to `3020fa75d73de06433fb162e64dcc830acdf9d6e`
+- updated Q-Server to [`0.48.1`](https://github.com/tonlabs/ton-q-server/blob/master/CHANGELOG.md#0481---2022-03-16)
**Attention! Devnet and Mainnet are going through an update that will lead to a breaking change in account format which may cause your nodes to stop working.
To fix it update your DApp Server to >=0.1.5 version.**
-
## [0.1.4] – 2022-01-14
### Improvements
-- ton-labs-node dependency is fixed to `3037a6cf279aac5826035c66d8b822fbdecf3e1a`
-- updated ArangoDB to 3.7.15
-- tuned ArangoDB memory limits
+- ton-labs-node dependency is fixed to `3037a6cf279aac5826035c66d8b822fbdecf3e1a`
+- updated ArangoDB to 3.7.15
+- tuned ArangoDB memory limits
## [0.1.3] – 2021-11-19
### Improvements
-- ton-labs-node dependency is fixed to `8b0fd1cd8dbcbbd55b278ed04842aa551f61e690`
-- ton-labs-node: implemented a mechanism with fixed dependencies
-- changed service to detect external IP
-- ton-labs-node: disabled RUST_BACKTRACE to improve performance
+- ton-labs-node dependency is fixed to `8b0fd1cd8dbcbbd55b278ed04842aa551f61e690`
+- ton-labs-node: implemented a mechanism with fixed dependencies
+- changed service to detect external IP
+- ton-labs-node: disabled RUST_BACKTRACE to improve performance
## [0.1.2] – 2021-10-21
### Improvements
-- ton-labs-node dependency is fixed to `9fd95b11b36e0af673002911fd843009cf1a3629`
-
+- ton-labs-node dependency is fixed to `9fd95b11b36e0af673002911fd843009cf1a3629`
+
### Fixed
-- ton-labs-node: OOM condition fix
-- ton-labs-node: fix for node sync failure after reboot
+- ton-labs-node: OOM condition fix
+- ton-labs-node: fix for node sync failure after reboot
## [0.1.1] – 2021-10-20
### Improvements
-- ton-labs-node dependency is fixed to `8acc92c2b2efb47f7f703b1c4a6722bfca648751`
-- ton-labs-node: updated RUST to 1.55
-
+- ton-labs-node dependency is fixed to `8acc92c2b2efb47f7f703b1c4a6722bfca648751`
+- ton-labs-node: updated RUST to 1.55
## [0.1.0] – 2021-09-27
### Improvements
-- ton-labs-node dependency is fixed to `f4a59efa0478e29305b207cfa2689df4a809ccf5`
-- Not-indexed arangodb was removed, now all queries, fast and slow are executed on the same arangodb.
-- Increased memlimit for Rust Node
-- Changed default Rust Node log config
-- Updated cp-kafka-connect to 5.3.6
-- Disabled Rust Node garbage collector
-
+- ton-labs-node dependency is fixed to `f4a59efa0478e29305b207cfa2689df4a809ccf5`
+- Not-indexed arangodb was removed, now all queries, fast and slow are executed on the same arangodb.
+- Increased memlimit for Rust Node
+- Changed default Rust Node log config
+- Updated cp-kafka-connect to 5.3.6
+- Disabled Rust Node garbage collector
+
### Fixed
-- ton-labs-node: Fixed possible error while block broadcast's checking (after node's restart)
-- ton-labs-types: Fixed cells counter for telemetry
-- ton-labs-vm: Fix dup, over, pushint printing in a trace
+- ton-labs-node: Fixed possible error while block broadcast's checking (after node's restart)
+- ton-labs-types: Fixed cells counter for telemetry
+- ton-labs-vm: Fix dup, over, pushint printing in a trace
diff --git a/README.md b/README.md
index 8cccb2c..0e00d5b 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-# Evernode DApp Server (DS)
-[Evernode Dapp Server](https://docs.evercloud.dev/products/dapp-server-ds) is a community (open source) version of [Evernode Platform](https://docs.evercloud.dev/) (client supernode with GraphQL API) for TVM blockchains (Everscale, Venom, TON, Gosh) that exposes [GraphQL API](https://docs.evercloud.dev/reference/graphql-api).
+# Evernode DApp Server
+Evernode DApp Server is a community (open source) version of [Ever Platform](https://docs.evercloud.dev/) (client supernode with GraphQL API) for TVM blockchains (Everscale, Venom, TON, Gosh) that exposes [GraphQL API](https://docs.evercloud.dev/reference/graphql-api).
-Compatible with [ever-sdk](https://github.com/tonlabs/ever-sdk), [everdev](https://github.com/tonlabs/everdev), [everscale-inpage-provider](https://github.com/broxus/everscale-inpage-provider), [evescale-standalone-client](https://github.com/broxus/everscale-inpage-provider) and other libraries and tools for TVM blockchains.
+Evernode DApp Server is compatible with [ever-sdk](https://github.com/tonlabs/ever-sdk), [everdev](https://github.com/tonlabs/everdev), [everscale-inpage-provider](https://github.com/broxus/everscale-inpage-provider), [evescale-standalone-client](https://github.com/broxus/everscale-standalone-client) and other libraries and tools for TVM blockchains.
@@ -13,92 +13,121 @@ Compatible with [ever-sdk](https://github.com/tonlabs/ever-sdk), [everdev](https
+This repository contains instructions on how to run your own free instance of Evernode Platform to connect your application to TVM blockchains.\
+The instructions and scripts were verified on Ubuntu 20.04.
-This HOWTO contains instructions on how to build and configure your own free instance of Evernode Platform to connect your application to Everscale. The instructions and scripts below were verified on Ubuntu 20.04.
+## Table of Contents
-# Table of Contents
-- [What is Evernode Dapp Server?](#what-is-evernode-dapp-server)
-- [Overview of technical architecture](#overview-of-technical-architecture)
-- [Getting Started](#getting-started)
- - [1. System Requirements](#1-system-requirements)
- - [2. Prerequisites](#2-prerequisites)
- - [2.1 Set the Environment](#21-set-the-environment)
- - [2.2 Install Dependencies](#22-install-dependencies)
- - [2.3 Deploy Full Node](#23-deploy-full-node)
-- [Check Node synchronization status](#Check-Node-synchronization-status)
-- [Stopping, restarting and deleting DApp Server](#stopping-restarting-and-deleting-dapp-server)
-- [Redeploying DApp Server](#redeploying-dapp-server)
+- [1. What is Evernode DApp Server?](#1-what-is-evernode-dapp-server)
+- [2. Overview of technical architecture](#2-overview-of-technical-architecture)
+ - [2.1 Service interaction diagram](#21-service-interaction-diagram)
+- [3. Getting Started](#3-getting-started)
+ - [3.1 Prerequisites](#31-prerequisites)
+ - [3.2 Configuration](#32-configuration)
+ - [3.3 Deployment](#33-deployment)
+ - [3.4 Tests](#34-tests)
+- [4. Notes](#4-notes)
+- [5. Related projects](#5-related-projects)
-# What is Evernode Dapp Server?
+## 1. What is Evernode DApp Server?
-Evernode DS is a set of services enabling you to work with Everscale blockchain.
+Evernode DApp Server is a set of services that provides a [GraphQL API](https://docs.evercloud.dev/reference/graphql-api) for TVM blockchains.
-The core element of Evernode DS is [Everscale node written in Rust](https://github.com/tonlabs/ton-labs-node) focused on performance and safety.\
-Evernode DS is a set of services serving EVER SDK GraphQL endpoint:
- - [Everscale GraphQL Server](https://github.com/tonlabs/ton-q-server) (aka Q-Server) for serving GraphQL queries.
- - Scalable multi-model database [ArangoDB](https://www.arangodb.com/documentation/) with the information about all blockchain entities (like accounts, blocks, transactions, etc.) stored over time
- - A high-throughput, low-latency streaming platform [Kafka](https://kafka.apache.org/documentation/) for communication between services.
- - StatsD exporter to collect and export metrics to Prometheus
+The client application can send messages to the blockchain and receive the results by performing the appropriate GraphQL operations:
-All the Evernode DS services can be easily deployed with Docker/Docker Compose wrapped into unix shell scripts, provided below.
+- Mutation - to send an external message to the blockchain.
+- Query - to query blockchain data.
+- Subscription - to subscribe for blockchain events.
-> **Note**: Rust node is included in the Evernode DS, and doesn't have to be installed separately.
+DApp Server consists of:
-# Overview of technical architecture
+- [Evernode](https://github.com/tonlabs/ever-node), written in Rust and focused on performance and safety,
+ is the core element of DApp Server.
-All system components run as docker containers inside one docker bridge network and are shown in the diagram below:
+- [Everscale GraphQL Server](https://github.com/tonlabs/ton-q-server) (referred as Q-Server) provides GraphQL
+ endpoint for sending messages and querying blockchain.
-
+- [ArangoDB](https://www.arangodb.com/documentation/) - multi-model database with the information about all
+ blockchain entities (like accounts, blocks, transactions, etc.) stored over time.
-# Getting Started
+- [Kafka](https://kafka.apache.org/documentation/) stream-processing platform for communication between services.
-## 1. System Requirements
-| Configuration | CPU (cores) | RAM (GiB) | Storage (GiB) | Network (Gbit/s)|
-|---|:---|:---|:---|:---|
-| Recommended |24|128|2000|1|
+- [StatsD exporter](https://github.com/prometheus/statsd_exporter) to collect and expose metrics to Prometheus.
-DApp Server is storage I/O bound, so NVMe SSD disks are recommended for the storage.
+## 2. Overview of technical architecture
-**Note**: To connect to a DApp Server you are running with client applications (such as [TONOS-CLI](https://github.com/tonlabs/tonos-cli#21-set-the-network-and-parameter-values)), it should have a domain name and a DNS record. Then its URL may be used to access it.
+Evernode DApp server provides the following endpoints:
-## 2. Prerequisites
-### 2.1 Set the Environment
-Adjust (if needed) `evernode-ds/scripts/env.sh`:
-- specify the network - use main.ton.dev for the main network and net.ton.dev for the developer network
-- specify notification email
+- https://your.domain/graphql
+- https://your.domain/arangodb (requires basic authorization)
+- https://your.domain/metrics
-Set environment variables:
+### 2.1 Service interaction diagram:
- $ cd ./scripts/
- $ . ./env.sh
+In this diagram, the bold arrows show how external messages are processed.
+- The client application sends a message (represented as a GraphQL mutation operation) to the Q-Server.
+- Q-Server sends this message (via Kafka) to Ever-node for processing.
+- Ever-node continuously provides (via Kafka) updated blockchain data as JSON documents (blocks, messages, transactions, account states) to ArangoDB.
+- Q-Server queries ArangoDB, thus knowing the result of the message execution.
-### 2.2 Install Dependencies
-Ubuntu 20.04:
+:
- $ ./install_deps.sh
-
-**Note**: Make sure to add your user to the docker group, or run subsequent command as superuser:
+This scripts run all services as docker containers inside one docker bridge network.\
+Recommended system configuration for this setup are shown below:
+| CPU (cores) | RAM (GiB) | Storage (GiB) | Network (Gbit/s) |
+| ----------- | :-------- | :------------------------------------- | :--------------- |
+| 24 | 128 | 2000. (NVMe SSD disks are recommended) | 1 |
- sudo usermod -a -G docker $USER
+See [4. Notes](#4-notes)
+## 3. Getting Started
-### 2.3 Deploy Full Node
-Deploy full node:
+### 3.1 Prerequisites
- $ ./deploy.sh 2>&1 | tee ./deploy.log
+- Host OS: Linux (all scripts tested on Ubuntu 20.04).
+- DApp server is accessed via HTTPS, so your server must have a fully qualified domain name.\
+ A self-signed certificate will be received on start-up and will be renewed automatically.
+- Installed Git, Docker Engine, Docker CLI, Docker Compose v2 or later.
+### 3.2 Configuration
-**Note**: the log generated by this command will be located in the `evernode-ds/scripts/` folder and can be useful for troubleshooting.
+3.2.1 Set variables
-# Check Node synchronization status
+Check `configure.sh` and set at least these environment variables:
-Use the following command to check if the node is synced:
+- NETWORK_TYPE
+- EVERNODE_FQDN
+- LETSENCRYPT_EMAIL
- docker exec rnode /ton-node/tools/console -C /ton-node/configs/console.json --cmd getstats
+3.2.2 Generate credentials to access the ArangoDB web interface
+
+Generate credentials (usernames and password) for basic authentication and update `.htpasswd` file.\
+You can generate it by running `htpasswd -nb `
+
+
+3.2.3 Run configuration script
+
+```
+$ ./configure.sh
+```
+
+This script creates `./deploy` directory
+
+### 3.3 Deployment
+
+Run `./up.sh`.
+
+After the script completes normally (it takes 30 min approx.), the node starts synchronizing its state, which can take several hours.\
+Use the following command to check the progress:
+
+```
+ docker exec ever-node /ever-node/tools/console -C /ever-node/configs/console.json --cmd getstats
+```
Script output example:
+
```
tonlabs console 0.1.286
COMMIT_ID: 5efe6bb8f2a974ba0e6b1ea3e58233632236e182
@@ -113,50 +142,59 @@ GIT_BRANCH: master
"public_overlay_key_id": "S4TaVdGitzTApe7GFCj8DbuRIkVEbg+ODzBxhQGIUG0=",
"timediff": 6,
"shards_timediff": 6,
- "in_current_vset_p34": false,
- "in_next_vset_p36": false,
- "last_applied_masterchain_block_id": {"shard":"-1:8000000000000000","seq_no":9194424,"rh":"ff88c27c9bc65762da222d6c14a163a96f7c74b65d1930735e23266a3b07ee8b","fh":"208bf95293feec1afdfdbd65a63c5f3ac4cd6a6fa15ac9e4e88fbfbd6a883edc"},
- "processed_workchain": "masterchain",
- "validation_stats": {},
- "collation_stats": {},
- "tps_10": 2,
- "tps_300": 2
+ ----%<---------------------
}
```
-If the `timediff` parameter is less than 10 seconds, synchronization with masterchain is complete.
-`"sync_status": "synchronization finished"` means synchronization with workchains is complete
-**Note**: The sync process may not start for up to one hour after node deployment, during which this command may result in error messages. If errors persist for more than an hour after deployment, review deployment log for errors and check the network status.
+If the `timediff` parameter is less than 10 seconds, synchronization with masterchain is complete.\
+`"sync_status": "synchronization finished"` means synchronization with workchains is complete.
+
+### 3.4 Tests
+To verify that the DApp server is actually functional, after the sync process is complete, run the test below.
+This test deploys wallet and transfers 0.5 tokens from the wallet to another address.
-# Stopping, restarting and deleting DApp Server
+```
+$ cd tests
+$ chmod o+w package-lock.json
+$ docker build --tag evernode_test .
+$ docker run --rm -e ENDPOINT=https:///graphql evernode_test
+```
-**Note**: call docker-compose commands from the `evernode-ds/docker-compose/ton-node` folder.
-
-To stop the node use the following command:
+#### Example output
- docker-compose stop
+```
+> npx ts-node src/wallet.ts
+You can topup your wallet from dashboard at https://dashboard.evercloud.dev
+Please send >= 1 tokens to 0:8a447eca3adde54414ab760d3633b96d5e7706a754450adfed587ac191c5b117
+awaiting...
+```
+
+> Here the test will block until you send some tokens to that address.\
+> In devnet you can do it using our dashboard at https://dashboard.evercloud.dev or telegram bot https://t.me/everdev_giver_bot
+
+```
+Account balance is: 100 tokens. Account type is 0
+Deploying wallet contract to address: 0:8a447eca3adde54414ab760d3633b96d5e7706a754450adfed587ac191c5b117 and waiting for transaction...
+Contract deployed. Transaction hash 318d2acfabd15a9e5ffd58c06c00074c67eca414f25e973c3332a8aeaa574bf1
+Sending 0.5 token to -1:7777777777777777777777777777777777777777777777777777777777777777
+Transfer completed. Transaction hash 54fdd8cce38c6078a25aae61c7deed2e5664c847c171048a814692440ee37610
+Transaction hash: 1d3bf7ef8a50ad38012f304a38c94fe4bca5bc1b50c2d4dd45ce2a71dc7c0921
+Transaction hash: 318d2acfabd15a9e5ffd58c06c00074c67eca414f25e973c3332a8aeaa574bf1
+Transaction hash: 54fdd8cce38c6078a25aae61c7deed2e5664c847c171048a814692440ee37610
+```
-To restart a stopped node use the following command:
-
- docker-compose restart
+Congratulations! Your DApp server is set up.
-To remove the node use the following commands:
-
- docker-compose down
- git reset --hard origin/master
- git clean -ffdx
-
-**Warning**: all local files and changes will be deleted from the git tree.
+## 4. Notes
-# Redeploying DApp Server
+- This repository is a "quick start" to get your first DApp server up and running.
+- The installation process is simple, written in pure bash and requires installation from scratch.
+- For simplicity, all services are deployed on one host and the system requirements for it are high, so
+ it makes sense to distribute services across different servers.\
+ After understanding this installation process, you can easily customize it for yourself.
-Before redeploying DApp server, make sure to remove the node and reset the git branch:
-
- cd evernode-ds/docker-compose/ton-node
- docker-compose down
- git reset --hard origin/master
- git clean -ffdx
+## 5. Related projects
-Otherwise redeployment will fail.
-When the branch is reset, repeat steps 2.1 - 2.3.
+- [itgoldio/everscale-dapp-server](https://github.com/itgoldio/everscale-dapp-server)
+ Consider this project if you prefer deployment via Ansible.
diff --git a/configure.sh b/configure.sh
new file mode 100755
index 0000000..6580a6d
--- /dev/null
+++ b/configure.sh
@@ -0,0 +1,61 @@
+#!/bin/bash -eE
+
+#----- To configure your Dapp server set at least these environment variables: -----
+export NETWORK_TYPE=net.ton.dev
+export EVERNODE_FQDN=your.domain.org
+export LETSENCRYPT_EMAIL=your@email.org
+export VALIDATOR_NAME=my_validator
+
+
+#----- Next variables can be used as reasonable defaults: -----
+
+export ADNL_PORT=30303
+#
+# Container memory limits
+#
+export NODE_MEMORY=64G
+export QSERVER_MEMORY=5G
+export ARANGO_MEMORY=32G
+export KAFKA_MEMORY=10G
+export CONNECT_MEMORY=5G
+
+
+export EVERNODE_GITHUB_REPO="https://github.com/tonlabs/ever-node"
+export EVERNODE_GITHUB_COMMIT_ID="a800b66765424e7870929e676ac6ea203390ff01"
+export EVERNODE_TOOLS_GITHUB_REPO="https://github.com/tonlabs/ever-node-tools.git"
+export EVERNODE_TOOLS_GITHUB_COMMIT_ID="master" # TODO, commit?
+
+Q_SERVER_GITHUB_REPO="https://github.com/tonlabs/ton-q-server"
+Q_SERVER_GITHUB_COMMIT="0.57.0"
+
+# This is a name of the internal (docker bridge) network. Set this name arbitrarily.
+export NETWORK=evernode_ds
+
+export COMPOSE_HTTP_TIMEOUT=120 # TODO: do we really need this?
+
+#
+# Create internal network if not exists
+#
+docker network inspect $NETWORK >/dev/null 2>&1 || docker network create $NETWORK -d bridge
+
+
+# Next lines create `deploy` directory as a copy of
+# `templates` directory and replace all {{VAR}} with enviroment variables
+rm -rf deploy ; cp -R templates deploy
+find deploy \
+ -type f \( -name '*.yml' -o -name *.html \) \
+ -not -path '*/ever-node/configs/*' \
+ -exec ./templates/templater.sh {} \;
+
+cp .htpasswd deploy/proxy
+mv deploy/proxy/vhost.d/{host.yourdomain.com,$EVERNODE_FQDN}
+
+
+# Run q-server
+rm -rf ./deploy/q-server/build/ton-q-server
+git clone ${Q_SERVER_GITHUB_REPO} --branch ${Q_SERVER_GITHUB_COMMIT} deploy/q-server/build/ton-q-server
+
+./templates/templater.sh deploy/ever-node/start_node.sh
+
+echo "Success! Output files are saved in the ./deploy directory"
+
diff --git a/docker-compose/arangodb/.env b/docker-compose/arangodb/.env
deleted file mode 100644
index a02f70c..0000000
--- a/docker-compose/arangodb/.env
+++ /dev/null
@@ -1,6 +0,0 @@
-ARANGO_ROOT_PASSWORD=iJJ9fWxb9Z6CS1aPagoW
-NETWORK_TYPE=placeholder
-INSTANCE_NAME=first
-ARANGO_SERVICE_SERVICE_HOST=arangodb
-ARANGO_SERVICE_SERVICE_PORT=8529
-ARANGO_MEMORY=32G
\ No newline at end of file
diff --git a/docker-compose/arangodb/arango-config b/docker-compose/arangodb/arango-config
deleted file mode 100644
index 80da328..0000000
--- a/docker-compose/arangodb/arango-config
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# Documentation:
-# https://docs.arangodb.com/latest/Manual/Administration/Configuration/
-# https://www.arangodb.com/docs/stable/programs-arangod-options.html
-
-[database]
-directory = /arango/db
-
-[server]
-endpoint = tcp://[::]:8529
-storage-engine = auto
-authentication = false
-# number of maximal server threads. use 0 to make arangod determine the
-# number of threads automatically, based on available CPUs
-# maximal-threads = 0
-# gather server statistics
-statistics = true
-#statistics-history = false
-
-[javascript]
-startup-directory = /usr/share/arangodb3/js
-app-path = /var/lib/arangodb3-apps
-
-# number of V8 contexts available for JavaScript execution. use 0 to
-# make arangod determine the number of contexts automatically.
-# v8-contexts = 0
-
-[foxx]
-# enable Foxx queues in the server
-# queues = true
-# interval (seconds) to use for polling jobs in Foxx queues
-# queues-poll-interval = 1
-
-[log]
-level = mmap=info
-level = performance=info
-level = warning
-output = +
-
-[cluster]
-
-[rocksdb]
-# encryption-keyfile=/your-encryption-file
-# 30% RAM in bytes (total RAM: 32 GiB)
-block-cache-size = 9830M
-# 30% RAM in bytes (total RAM: 32 GiB)
-total-write-buffer-size = 9830M
-enforce-block-cache-size-limit = true
-
-[query]
-memory-limit = 1000M
-
-[cache]
-# 20% RAM in bytes (total RAM: 32 GiB)
-cache.size = 6553M
diff --git a/docker-compose/arangodb/build/.dockerignore b/docker-compose/arangodb/build/.dockerignore
deleted file mode 100644
index 9414382..0000000
--- a/docker-compose/arangodb/build/.dockerignore
+++ /dev/null
@@ -1 +0,0 @@
-Dockerfile
diff --git a/docker-compose/arangodb/build/Dockerfile b/docker-compose/arangodb/build/Dockerfile
deleted file mode 100644
index 4ed3ee9..0000000
--- a/docker-compose/arangodb/build/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM arangodb:3.7.15
-
-RUN apk add bash
-RUN rm /entrypoint.sh
-ADD arango /arango
-RUN chmod +x /arango/entrypoint
-RUN mkdir -p '/var/lib/arangodb3'; \
- mkdir -p '/var/lib/arangodb3-apps'; \
- chmod +w '/var/lib/arangodb3'; \
- chmod +w '/var/lib/arangodb3-apps'
-EXPOSE 80
-EXPOSE 8529
-ENTRYPOINT ["/arango/entrypoint"]
diff --git a/docker-compose/arangodb/build/arango/entrypoint b/docker-compose/arangodb/build/arango/entrypoint
deleted file mode 100644
index 332b8d9..0000000
--- a/docker-compose/arangodb/build/arango/entrypoint
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/bin/bash -eEx
-
-ARANGO_INIT_PORT=8529
-ARANGO_ENDPOINT="tcp://127.0.0.1:$ARANGO_INIT_PORT"
-export GLIBCXX_FORCE_NEW=1
-
-# check for numa
-NUMACTL=""
-
-if [ -d /sys/devices/system/node/node1 ] && [ -f /proc/self/numa_maps ]; then
- if [ "$NUMA" = "" ]; then
- NUMACTL="numactl --interleave=all"
- elif [ "$NUMA" != "disable" ]; then
- NUMACTL="numactl --interleave=$NUMA"
- fi
-
- if [ "$NUMACTL" != "" ]; then
- if $NUMACTL echo >/dev/null 2>&1; then
- echo "using NUMA $NUMACTL"
- else
- echo "cannot start with NUMA $NUMACTL: please ensure that docker is running with --cap-add SYS_NICE"
- NUMACTL=""
- fi
- fi
-fi
-
-# Update if needed
-$NUMACTL arangod --config /arango/config \
- --server.endpoint $ARANGO_ENDPOINT \
- --server.authentication=false \
- --log.foreground-tty true \
- --database.auto-upgrade true || exit 1
-
-$NUMACTL arangod --config /arango/config \
- --server.endpoint $ARANGO_ENDPOINT \
- --server.authentication=false \
- --log.foreground-tty true &
-pid="$!"
-counter=0
-ARANGO_UP=0
-
-while [ "$ARANGO_UP" = "0" ]; do
- if [ $counter -gt 0 ]; then
- sleep 1
- echo '.'
- fi
-
- if [ "$counter" -gt 100 ]; then
- echo "ArangoDB didn't start correctly during init"
- cat /tmp/init-log
- exit 1
- fi
-
- counter=$((counter + 1))
- ARANGO_UP=1
-
- $NUMACTL arangosh \
- --server.authentication=false \
- --javascript.execute-string "db._version()" \
- >/dev/null 2>&1 || ARANGO_UP=0
-done
-
-if [ "$(id -u)" = "0" ]; then
- foxx server set default http://127.0.0.1:$ARANGO_INIT_PORT
-else
- echo Not setting foxx server default because we are not root.
-fi
-
-echo "Running init db scripts"
-for f in /arango/initdb.d/*; do
- case "$f" in
- *.sh)
- echo "$0: running $f"
- # shellcheck disable=SC1090
- . "$f"
- ;;
- *.js)
- echo "$0: running $f"
- $NUMACTL arangosh --server.authentication false \
- --javascript.execute "$f"
- ;;
- */dumps)
- echo "$0: restoring databases"
- for d in "$f/"*; do
- # shellcheck disable=SC2001
- DBName=$(echo "${d}" | sed "s;$f/;;")
- echo "restoring $d into ${DBName}"
- $NUMACTL arangorestore \
- --server.authentication false \
- --create-database true \
- --include-system-collections true \
- --server.database "$DBName" \
- --input-directory "$d"
- done
- echo
- ;;
- esac
-done
-
-if [ "$(id -u)" = "0" ]; then
- foxx server remove default
-fi
-
-if ! kill -s TERM "$pid" || ! wait "$pid"; then
- echo >&2 'ArangoDB Init failed.'
- exit 1
-fi
-
-echo "Database initialized..."
-exec $NUMACTL arangod --config /arango/config \
- --server.authentication=false
diff --git a/docker-compose/arangodb/docker-compose.yml b/docker-compose/arangodb/docker-compose.yml
deleted file mode 100644
index a2b7208..0000000
--- a/docker-compose/arangodb/docker-compose.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-version: '2.3'
-services:
- arangodb:
- build:
- context: ./build
- # image: tonlabs/arango:latest
- container_name: arangodb
- restart: unless-stopped
- environment:
- ARANGO_NO_AUTH: 1
- VIRTUAL_HOST: arango.yourdomain.com
- VIRTUAL_PORT: 8529
- LETSENCRYPT_HOST: arango.yourdomain.com
- LETSENCRYPT_EMAIL: "email for notification"
- ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY: "${ARANGO_MEMORY}"
- networks:
- - proxy_nw
- volumes:
- - db3:/var/lib/arangodb3
- - data:/arango/db
- - ./arango-config:/arango/config
- expose:
- - "8529"
- mem_limit: "${ARANGO_MEMORY}"
-
-networks:
- proxy_nw:
- external: true
-volumes:
- data:
- db3:
diff --git a/docker-compose/kafka/.env b/docker-compose/kafka/.env
deleted file mode 100644
index 379f6e4..0000000
--- a/docker-compose/kafka/.env
+++ /dev/null
@@ -1 +0,0 @@
-ADVERTISED_LISTENER=kafka
diff --git a/docker-compose/kafka/arangodb-connector-download.url b/docker-compose/kafka/arangodb-connector-download.url
deleted file mode 100644
index 551b120..0000000
--- a/docker-compose/kafka/arangodb-connector-download.url
+++ /dev/null
@@ -1 +0,0 @@
-https://www.confluent.io/connector/kafka-connect-arangodb/#download
diff --git a/docker-compose/kafka/build_check/Dockerfile b/docker-compose/kafka/build_check/Dockerfile
deleted file mode 100644
index 0bd813c..0000000
--- a/docker-compose/kafka/build_check/Dockerfile
+++ /dev/null
@@ -1,9 +0,0 @@
-FROM confluentinc/cp-kafka-connect:5.3.6
-RUN apt update && apt -y --force-yes install jq bsdmainutils
-COPY check.sh /work/check.sh
-COPY create_topics.sh /work/create_topics.sh
-COPY create_connectors.sh /work/create_connectors.sh
-COPY connect-cli /usr/bin/connect-cli
-COPY /connectors/ /work/connectors/
-COPY entrypoint.sh /entrypoint.sh
-ENTRYPOINT ["/entrypoint.sh"]
diff --git a/docker-compose/kafka/build_check/check.sh b/docker-compose/kafka/build_check/check.sh
deleted file mode 100755
index 90e8ab0..0000000
--- a/docker-compose/kafka/build_check/check.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env sh
-
-# List current connectors and status
-curl -s "http://$1:8083/connectors"| jq '.[]'| sed -e 's/"//g' | \
-xargs -I{connector_name} curl -s "http://$1:8083/connectors/{connector_name}/status"| \
-jq -c -M '[.name,.connector.state,.tasks[].state]|join(":|:")'| column -s : -t| sed 's/\"//g'| sort | tee /work/result.txt
-
-# Restart any connector tasks that are FAILED
-curl -s "http://$1:8083/connectors" | \
- jq '.[]' | sed -e 's/"//g' | \
- xargs -I{connector_name} curl -s "http://$1:8083/connectors/{connector_name}/status" | \
- jq -c -M '[select(.tasks[].state=="FAILED") | .name,"§±§",.tasks[].id]' | \
- grep -v "\[\]"| \
- sed -e 's/^\[\"//g'| sed -e 's/\",\"§±§\",/\/tasks\//g'|sed -e 's/\]$//g'| \
- xargs -I{connector_and_task} curl -v -X POST "http://$1:8083/connectors/{connector_and_task}/restart"
-
-# put error status
-grep "FAILED" -qs /work/result.txt && exit 1 || exit 0
diff --git a/docker-compose/kafka/build_check/connect-cli b/docker-compose/kafka/build_check/connect-cli
deleted file mode 100755
index 88d9870..0000000
Binary files a/docker-compose/kafka/build_check/connect-cli and /dev/null differ
diff --git a/docker-compose/kafka/build_check/connectors/arangodb-accounts-sink.properties b/docker-compose/kafka/build_check/connectors/arangodb-accounts-sink.properties
deleted file mode 100644
index bec0f48..0000000
--- a/docker-compose/kafka/build_check/connectors/arangodb-accounts-sink.properties
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright 2018-2019 TON DEV SOLUTIONS LTD.
-#
-# Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use
-# this file except in compliance with the License. You may obtain a copy of the
-# License at:
-#
-# https://www.ton.dev/licenses
-#
-# 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 TON DEV software governing permissions and limitations
-# under the License.
-#
-
-
-connector.class=io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector
-name=arangodb-accounts-sink
-tasks.max=1
-topics=accounts
-
-arangodb.host=arangodb
-arangodb.user=root
-arangodb.password=iJJ9fWxb9Z6CS1aPagoW
-arangodb.port=8529
-arangodb.database.name=blockchain
-
-transforms=KeyTransform
-transforms.KeyTransform.field=id
-transforms.KeyTransform.type=org.apache.kafka.connect.transforms.HoistField$Key
-
-key.converter.schemas.enable=false
-key.converter=org.apache.kafka.connect.json.JsonConverter
-value.converter.schemas.enable=false
-value.converter=org.apache.kafka.connect.json.JsonConverter
\ No newline at end of file
diff --git a/docker-compose/kafka/build_check/connectors/arangodb-blocks-signatures-sink.properties b/docker-compose/kafka/build_check/connectors/arangodb-blocks-signatures-sink.properties
deleted file mode 100644
index 27dafdb..0000000
--- a/docker-compose/kafka/build_check/connectors/arangodb-blocks-signatures-sink.properties
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright 2018-2019 TON DEV SOLUTIONS LTD.
-#
-# Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use
-# this file except in compliance with the License. You may obtain a copy of the
-# License at:
-#
-# https://www.ton.dev/licenses
-#
-# 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 TON DEV software governing permissions and limitations
-# under the License.
-#
-
-connector.class=io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector
-name=arangodb-blocks-signatures-sink
-tasks.max=1
-topics=blocks_signatures
-
-arangodb.host=arangodb
-arangodb.user=root
-arangodb.password=iJJ9fWxb9Z6CS1aPagoW
-arangodb.port=8529
-arangodb.database.name=blockchain
-
-transforms=KeyTransform
-transforms.KeyTransform.field=id
-transforms.KeyTransform.type=org.apache.kafka.connect.transforms.HoistField$Key
-
-key.converter.schemas.enable=false
-key.converter=org.apache.kafka.connect.json.JsonConverter
-value.converter.schemas.enable=false
-value.converter=org.apache.kafka.connect.json.JsonConverter
\ No newline at end of file
diff --git a/docker-compose/kafka/build_check/connectors/arangodb-blocks-sink.properties b/docker-compose/kafka/build_check/connectors/arangodb-blocks-sink.properties
deleted file mode 100644
index 6c11973..0000000
--- a/docker-compose/kafka/build_check/connectors/arangodb-blocks-sink.properties
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright 2018-2019 TON DEV SOLUTIONS LTD.
-#
-# Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use
-# this file except in compliance with the License. You may obtain a copy of the
-# License at:
-#
-# https://www.ton.dev/licenses
-#
-# 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 TON DEV software governing permissions and limitations
-# under the License.
-#
-
-connector.class=io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector
-name=arangodb-blocks-sink
-tasks.max=1
-topics=blocks
-
-arangodb.host=arangodb
-arangodb.user=root
-arangodb.password=iJJ9fWxb9Z6CS1aPagoW
-arangodb.port=8529
-arangodb.database.name=blockchain
-
-transforms=KeyTransform
-transforms.KeyTransform.field=id
-transforms.KeyTransform.type=org.apache.kafka.connect.transforms.HoistField$Key
-
-key.converter.schemas.enable=false
-key.converter=org.apache.kafka.connect.json.JsonConverter
-value.converter.schemas.enable=false
-value.converter=org.apache.kafka.connect.json.JsonConverter
\ No newline at end of file
diff --git a/docker-compose/kafka/build_check/connectors/arangodb-messages-sink.properties b/docker-compose/kafka/build_check/connectors/arangodb-messages-sink.properties
deleted file mode 100644
index c5008de..0000000
--- a/docker-compose/kafka/build_check/connectors/arangodb-messages-sink.properties
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright 2018-2019 TON DEV SOLUTIONS LTD.
-#
-# Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use
-# this file except in compliance with the License. You may obtain a copy of the
-# License at:
-#
-# https://www.ton.dev/licenses
-#
-# 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 TON DEV software governing permissions and limitations
-# under the License.
-#
-
-
-connector.class=io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector
-name=arangodb-messages-sink
-tasks.max=1
-topics=messages
-
-arangodb.host=arangodb
-arangodb.user=root
-arangodb.password=iJJ9fWxb9Z6CS1aPagoW
-arangodb.port=8529
-arangodb.database.name=blockchain
-arangodb.insert.overwritemode=update
-
-transforms=KeyTransform
-transforms.KeyTransform.field=id
-transforms.KeyTransform.type=org.apache.kafka.connect.transforms.HoistField$Key
-
-key.converter.schemas.enable=false
-key.converter=org.apache.kafka.connect.json.JsonConverter
-value.converter.schemas.enable=false
-value.converter=org.apache.kafka.connect.json.JsonConverter
diff --git a/docker-compose/kafka/build_check/connectors/arangodb-transactions-sink.properties b/docker-compose/kafka/build_check/connectors/arangodb-transactions-sink.properties
deleted file mode 100644
index 730c1e8..0000000
--- a/docker-compose/kafka/build_check/connectors/arangodb-transactions-sink.properties
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright 2018-2019 TON DEV SOLUTIONS LTD.
-#
-# Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use
-# this file except in compliance with the License. You may obtain a copy of the
-# License at:
-#
-# https://www.ton.dev/licenses
-#
-# 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 TON DEV software governing permissions and limitations
-# under the License.
-#
-
-
-connector.class=io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector
-name=arangodb-transactions-sink
-tasks.max=1
-topics=transactions
-
-arangodb.host=arangodb
-arangodb.user=root
-arangodb.password=iJJ9fWxb9Z6CS1aPagoW
-arangodb.port=8529
-arangodb.database.name=blockchain
-
-transforms=KeyTransform
-transforms.KeyTransform.field=id
-transforms.KeyTransform.type=org.apache.kafka.connect.transforms.HoistField$Key
-
-key.converter.schemas.enable=false
-key.converter=org.apache.kafka.connect.json.JsonConverter
-value.converter.schemas.enable=false
-value.converter=org.apache.kafka.connect.json.JsonConverter
\ No newline at end of file
diff --git a/docker-compose/kafka/build_check/create_connectors.sh b/docker-compose/kafka/build_check/create_connectors.sh
deleted file mode 100755
index 5ab2492..0000000
--- a/docker-compose/kafka/build_check/create_connectors.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-for connector in $(ls /work/connectors)
-do
- connect-cli create -e http://connect:8083/ $(awk -F "." '{print $1}' <<< ${connector}) < /work/connectors/${connector}
- sleep 10s
-done
diff --git a/docker-compose/kafka/build_check/create_topics.sh b/docker-compose/kafka/build_check/create_topics.sh
deleted file mode 100755
index 2676e1e..0000000
--- a/docker-compose/kafka/build_check/create_topics.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-
-kafka-topics --create --zookeeper zookeeper:2181 --topic accounts --replication-factor 1 --partitions 20 --if-not-exists
-sleep 2
-kafka-topics --create --zookeeper zookeeper:2181 --topic transactions --replication-factor 1 --partitions 40 --if-not-exists
-sleep 2
-kafka-topics --create --zookeeper zookeeper:2181 --topic blocks --replication-factor 1 --partitions 5 --if-not-exists
-sleep 2
-kafka-topics --create --zookeeper zookeeper:2181 --topic messages --replication-factor 1 --partitions 60 --if-not-exists
-sleep 2
-kafka-topics --create --zookeeper zookeeper:2181 --topic requests --replication-factor 1 --partitions 30 --if-not-exists
-sleep 2
-kafka-topics --create --zookeeper zookeeper:2181 --topic blocks_signatures --replication-factor 1 --partitions 5 --if-not-exists
-sleep 2
-kafka-topics --alter --zookeeper zookeeper:2181 --topic accounts --partitions 20 --if-exists
-sleep 2
-kafka-topics --alter --zookeeper zookeeper:2181 --topic transactions --partitions 40 --if-exists
-sleep 2
-kafka-topics --alter --zookeeper zookeeper:2181 --topic blocks --partitions 5 --if-exists
-sleep 2
-kafka-topics --alter --zookeeper zookeeper:2181 --topic messages --partitions 60 --if-exists
-sleep 2
-kafka-topics --alter --zookeeper zookeeper:2181 --topic requests --partitions 30 --if-exists
-sleep 2
-kafka-topics --alter --zookeeper zookeeper:2181 --topic blocks_signatures --partitions 5 --if-exists
diff --git a/docker-compose/kafka/build_check/entrypoint.sh b/docker-compose/kafka/build_check/entrypoint.sh
deleted file mode 100755
index 677da94..0000000
--- a/docker-compose/kafka/build_check/entrypoint.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-/work/create_topics.sh
-/work/create_connectors.sh
-
-exec tail -f /dev/null
-
diff --git a/docker-compose/kafka/kafka-connect-cli.url b/docker-compose/kafka/kafka-connect-cli.url
deleted file mode 100644
index a3c12f2..0000000
--- a/docker-compose/kafka/kafka-connect-cli.url
+++ /dev/null
@@ -1 +0,0 @@
-https://github.com/Landoop/kafka-connect-tools/releases/download/v1.0.6/connect-cli
diff --git a/docker-compose/kafka/launch.sh b/docker-compose/kafka/launch.sh
deleted file mode 100755
index 35c2f68..0000000
--- a/docker-compose/kafka/launch.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright 2016 Confluent 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.
-
-# JMX settings
-if [ -z "$KAFKA_REST_JMX_OPTS" ]; then
- KAFKA_REST_JMX_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false "
-fi
-
-# The JMX client needs to be able to connect to java.rmi.server.hostname.
-# The default for bridged n/w is the bridged IP so you will only be able to connect from another docker container.
-# For host n/w, this is the IP that the hostname on the host resolves to.
-
-# If you have more that one n/w configured, hostname -i gives you all the IPs,
-# the default is to pick the first IP (or network).
-export KAFKA_REST_JMX_HOSTNAME=${KAFKA_REST_JMX_HOSTNAME:-$(hostname -i | cut -d" " -f1)}
-
-# JMX port to use
-if [ $KAFKA_REST_JMX_PORT ]; then
- export JMX_PORT=$KAFKA_REST_JMX_PORT
-export KAFKA_REST_JMX_OPTS="$KAFKA_REST_JMX_OPTS -Djava.rmi.server.hostname=$KAFKA_REST_JMX_HOSTNAME -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT -Dcom.sun.management.jmxremote.port=$JMX_PORT"
-fi
-echo "access.control.allow.origin=*" >> /etc/kafka-rest/kafka-rest.properties
-echo "access.control.allow.methods=GET,POST,PUT,DELETE,OPTIONS,HEAD" >> /etc/kafka-rest/kafka-rest.properties
-
-echo "===> Launching ${COMPONENT} ... "
-exec "${COMPONENT}"-start /etc/"${COMPONENT}"/"${COMPONENT}".properties
diff --git a/docker-compose/proxy/build/Dockerfile b/docker-compose/proxy/build/Dockerfile
deleted file mode 100644
index 8184419..0000000
--- a/docker-compose/proxy/build/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-FROM jwilder/nginx-proxy:0.8.0
-#FROM jwilder/nginx-proxy:latest
-
-RUN sed -i 's/worker_connections .*;/worker_connections 10240;/' /etc/nginx/nginx.conf
-RUN apt update && \
- apt install -y net-tools iproute2 watch vim && \
- rm -rf /var/lib/apt/lists/*
diff --git a/docker-compose/proxy/htpasswd/arango.yourdomain.com b/docker-compose/proxy/htpasswd/arango.yourdomain.com
deleted file mode 100644
index b0dc5db..0000000
--- a/docker-compose/proxy/htpasswd/arango.yourdomain.com
+++ /dev/null
@@ -1 +0,0 @@
-user:
diff --git a/docker-compose/proxy/htpasswd/arangoni.yourdomain.com b/docker-compose/proxy/htpasswd/arangoni.yourdomain.com
deleted file mode 100644
index fbd5ed4..0000000
--- a/docker-compose/proxy/htpasswd/arangoni.yourdomain.com
+++ /dev/null
@@ -1 +0,0 @@
-user:
\ No newline at end of file
diff --git a/docker-compose/q-server/.env b/docker-compose/q-server/.env
deleted file mode 100644
index 28ed43a..0000000
--- a/docker-compose/q-server/.env
+++ /dev/null
@@ -1,7 +0,0 @@
-Q_DATA_MUT=http://arangodb:8529
-Q_DATA_HOT=http://arangodb:8529
-Q_REQUESTS_MODE=kafka
-Q_REQUESTS_SERVER=kafka:9092
-Q_REQUESTS_TOPIC=requests
-Q_QUERY_MAX_RUNTIME=60
-Q_SLOW_QUERIES=enable
diff --git a/docker-compose/q-server/build/.dockerignore b/docker-compose/q-server/build/.dockerignore
deleted file mode 100644
index 2833d34..0000000
--- a/docker-compose/q-server/build/.dockerignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.git/
-Dockerfile
diff --git a/docker-compose/q-server/build/Dockerfile b/docker-compose/q-server/build/Dockerfile
deleted file mode 100644
index 368418a..0000000
--- a/docker-compose/q-server/build/Dockerfile
+++ /dev/null
@@ -1,46 +0,0 @@
-FROM node:14-buster
-
-USER root
-
-RUN apt-get update && apt-get install -y apt-utils
-
-RUN apt-get update && apt-get install -y \
- build-essential \
- sudo \
- gcc-multilib \
- cmake \
- libxcb-xfixes0-dev \
- g++ \
- pkg-config \
- jq \
- libcurl4-openssl-dev \
- libelf-dev \
- libdw-dev \
- binutils-dev \
- libiberty-dev \
- python \
- zlib1g-dev \
- && rm -rf /var/lib/apt/lists/*
-
-RUN echo "deb http://deb.debian.org/debian stretch-backports main contrib non-free # available after stretch release" >> /etc/apt/sources.list && \
- apt-get update && apt-get -y upgrade && apt-get install -y clang-6.0 && rm -rf /var/lib/apt/lists/*
-
-RUN npm install -g node-gyp && npm install -g forever && npm install -g forever-service
-
-RUN usermod -aG sudo node \
- && echo "node ALL=(root) NOPASSWD: /usr/local/bin/forever-service, /usr/sbin/service webapi stop, /usr/sbin/service webapi start" >> /etc/sudoers
-
-USER node
-
-RUN cd /tmp && wget https://sh.rustup.rs -O rust.sh && bash rust.sh -y && rm rust.sh
-
-ENV PATH="/home/node/.cargo/bin:${PATH}"
-
-RUN rustup component add rustfmt-preview && rustup target add i686-unknown-linux-gnu
-
-WORKDIR /home/node
-USER node
-COPY ton-q-server /home/node/
-RUN npm ci && npm run tsc && npm ci --production
-EXPOSE 4000
-ENTRYPOINT ["node", "index.js"]
diff --git a/docker-compose/q-server/docker-compose.yml b/docker-compose/q-server/docker-compose.yml
deleted file mode 100644
index 2f688ef..0000000
--- a/docker-compose/q-server/docker-compose.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-version: '2.3'
-services:
- q-server:
- build:
- context: ./build
- # image: tonlabs/q-server:latest
- container_name: q-server
- restart: unless-stopped
- environment:
- - VIRTUAL_HOST=q-server
- - VIRTUAL_PORT=4000
- - Q_DATA_MUT
- - Q_DATA_HOT
- - Q_REQUESTS_MODE
- - Q_REQUESTS_SERVER
- - Q_REQUESTS_TOPIC
- - Q_QUERY_MAX_RUNTIME
- - Q_SLOW_QUERIES
- networks:
- - proxy_nw
- expose:
- - "4000"
- mem_limit: 5G
-networks:
- proxy_nw:
- external: true
diff --git a/docker-compose/statsd/.env b/docker-compose/statsd/.env
deleted file mode 100644
index 9f26642..0000000
--- a/docker-compose/statsd/.env
+++ /dev/null
@@ -1,5 +0,0 @@
-IMAGE=prom/statsd-exporter:v0.12.2
-ARGS=--statsd.mapping-config=/statsd-mappings/statsd-mapping.yaml
-UDP_PORT=9125
-TCP_PORT=9102
-IntIP=
diff --git a/docker-compose/statsd/docker-compose.yml b/docker-compose/statsd/docker-compose.yml
deleted file mode 100644
index c3d9ea2..0000000
--- a/docker-compose/statsd/docker-compose.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-version: '2.2'
-services:
- statsd:
- # build:
- # context: ./build
- image: "${IMAGE}"
- container_name: statsd
- restart: unless-stopped
- expose:
- - "${UDP_PORT}/udp"
- ports:
- - "${IntIP}:${TCP_PORT}:${TCP_PORT}"
- networks:
- - proxy_nw
- volumes:
- - ./statsd-mapping.yaml:/statsd-mappings/statsd-mapping.yaml
- command: ["${ARGS}"]
- logging:
- driver: json-file
- options:
- max-size: "100m"
- max-file: "10"
-networks:
- proxy_nw:
- external: true
diff --git a/docker-compose/ton-node/.env b/docker-compose/ton-node/.env
deleted file mode 100644
index bfd06c7..0000000
--- a/docker-compose/ton-node/.env
+++ /dev/null
@@ -1,9 +0,0 @@
-NETWORK_TYPE=placeholder
-MEM_LIMIT=64G
-CONFIGS_PATH=/ton-node/configs
-STATSD_DOMAIN=statsd:
-STATSD_PORT=9125
-ADNL_PORT=30303
-VALIDATOR_NAME=my_validator
-# Supported values: normal, bash
-NODE_CMD_1=normal
diff --git a/docker-compose/ton-node/build/.dockerignore b/docker-compose/ton-node/build/.dockerignore
deleted file mode 100644
index 2833d34..0000000
--- a/docker-compose/ton-node/build/.dockerignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.git/
-Dockerfile
diff --git a/docker-compose/ton-node/docker-compose.yml b/docker-compose/ton-node/docker-compose.yml
deleted file mode 100644
index 0bb516c..0000000
--- a/docker-compose/ton-node/docker-compose.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-version: '2.2'
-services:
- node:
- build:
- context: ./build
- # image: "${NODE_IMAGE}"
- container_name: rnode
- restart: unless-stopped
- environment:
- ADNL_PORT:
- VALIDATOR_NAME:
- NETWORK_TYPE:
- CONFIGS_PATH:
- STATSD_DOMAIN:
- STATSD_PORT:
- STAKE:
- MSIG_ENABLE:
- SDK_URL:
- ports:
- - "${ADNL_PORT}:${ADNL_PORT}/udp"
- networks:
- - proxy_nw
- volumes:
- - ./configs/:/ton-node/configs/
- - ./scripts/:/ton-node/scripts/
- - ./logs/:/ton-node/logs/
- - DB:/ton-node/node_db/
- - /tmp/metrics/:/tmp/metrics/
- entrypoint: /ton-node/scripts/entrypoint.sh
- command: ["${NODE_CMD_1}"]
- mem_limit: "${MEM_LIMIT}"
- logging:
- driver: json-file
- options:
- max-size: "1000m"
- max-file: "100"
- cap_add:
- - SYS_PTRACE
-networks:
- proxy_nw:
- external: true
-volumes:
- DB:
diff --git a/docker-compose/ton-node/scripts/generate_console_config.sh b/docker-compose/ton-node/scripts/generate_console_config.sh
deleted file mode 100755
index ed5493b..0000000
--- a/docker-compose/ton-node/scripts/generate_console_config.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/bash -eEx
-
-if [ "$DEBUG" = "yes" ]; then
- set -x
-fi
-
-export TON_NODE_ROOT_DIR="/ton-node"
-export TON_NODE_CONFIGS_DIR="${TON_NODE_ROOT_DIR}/configs"
-export TON_NODE_TOOLS_DIR="${TON_NODE_ROOT_DIR}/tools"
-export TON_NODE_LOGS_DIR="${TON_NODE_ROOT_DIR}/logs"
-export RNODE_CONSOLE_SERVER_PORT="3031"
-
-HOSTNAME=$(hostname -f)
-TMP_DIR="/tmp/$(basename "$0" .sh)_$$"
-rm -rf "${TMP_DIR}"
-mkdir -p "${TMP_DIR}"
-
-"${TON_NODE_TOOLS_DIR}/keygen" >"${TON_NODE_CONFIGS_DIR}/${HOSTNAME}_console_client_keys.json"
-cat "${TON_NODE_CONFIGS_DIR}/${HOSTNAME}_console_client_keys.json"
-jq -c .public "${TON_NODE_CONFIGS_DIR}/${HOSTNAME}_console_client_keys.json" >"${TON_NODE_CONFIGS_DIR}/console_client_public.json"
-
-jq ".control_server_port = ${RNODE_CONSOLE_SERVER_PORT}" "${TON_NODE_CONFIGS_DIR}/default_config.json" >"${TMP_DIR}/default_config.json.tmp"
-cp "${TMP_DIR}/default_config.json.tmp" "${TON_NODE_CONFIGS_DIR}/default_config.json"
-
-# Generate initial config.json
-cd "${TON_NODE_ROOT_DIR}" && "${TON_NODE_ROOT_DIR}/ton_node" --configs "${TON_NODE_CONFIGS_DIR}" --ckey "$(cat "${TON_NODE_CONFIGS_DIR}/console_client_public.json")" &
-
-sleep 10
-
-if [ ! -f "${TON_NODE_CONFIGS_DIR}/config.json" ]; then
- echo "ERROR: ${TON_NODE_CONFIGS_DIR}/config.json does not exist"
- exit 1
-fi
-
-cat "${TON_NODE_CONFIGS_DIR}/config.json"
-
-if [ ! -f "${TON_NODE_CONFIGS_DIR}/console_config.json" ]; then
- echo "ERROR: ${TON_NODE_CONFIGS_DIR}/console_config.json does not exist"
- exit 1
-fi
-
-cat "${TON_NODE_CONFIGS_DIR}/console_config.json"
-
-jq ".client_key = $(jq .private "${TON_NODE_CONFIGS_DIR}/${HOSTNAME}_console_client_keys.json")" "${TON_NODE_CONFIGS_DIR}/console_config.json" >"${TMP_DIR}/console_config.json.tmp"
-jq ".config = $(cat "${TMP_DIR}/console_config.json.tmp")" "${TON_NODE_CONFIGS_DIR}/console_template.json" >"${TON_NODE_CONFIGS_DIR}/console.json"
-rm -f "${TON_NODE_CONFIGS_DIR}/console_config.json"
-
-rm -rf "${TMP_DIR}"
diff --git a/docker-compose/web.root/.env b/docker-compose/web.root/.env
deleted file mode 100644
index cfb97af..0000000
--- a/docker-compose/web.root/.env
+++ /dev/null
@@ -1 +0,0 @@
-HOSTpublic=host.yourdomain.com
diff --git a/docker-compose/web.root/docker-compose.yml b/docker-compose/web.root/docker-compose.yml
deleted file mode 100644
index dda052d..0000000
--- a/docker-compose/web.root/docker-compose.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-version: '2'
-services:
- web.root:
- image: nginx:1.13.12
- container_name: web.root
- restart: unless-stopped
- environment:
- - VIRTUAL_HOST=${HOSTpublic}
- - LETSENCRYPT_HOST=${HOSTpublic}
- - LETSENCRYPT_EMAIL="for notification"
- networks:
- - proxy_nw
- volumes:
- - ./index.html:/usr/share/nginx/html/index.html
- expose:
- - "80"
-networks:
- proxy_nw:
- external: true
diff --git a/docker-compose/web.root/index.html b/docker-compose/web.root/index.html
deleted file mode 100644
index 5b2fe65..0000000
--- a/docker-compose/web.root/index.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/docs/system_components.svg b/docs/system_components.svg
index cce4767..cd41567 100644
--- a/docs/system_components.svg
+++ b/docs/system_components.svg
@@ -1,3 +1,4 @@
+
-1. Queries 2. Subscriptions
1. Queries... 3. External... q-server... http proxy... web.root... letsencrypt... arangodb External... kafka JSON documents: blocks, accounts, messages,transactions
JSON documents:... connect... zookeeper
statsd Exporter for Prometheus
statsd... Parsed blockchain data:
blocks, accounts, messages,
transactions
Parsed blockchain data:... metrics https Client sends GraphQL operations:
Query Subscription Mutation (external messages) Client sends GraphQL operations:... node
ADNL_port/udp Internal network (docker bridge)
Internal network... StatsD... Text is not SVG - cannot display
\ No newline at end of file
+Queries and
subscriptions
Queries and... q-server... /graphql metrics proxy (nginx) HTTPS termination
proxy (nginx)... arangodb kafka JSON docs: blocks, accounts, messages,transactions
JSON docs:... connect... zookeeper
statsd exporter for Prometheus
statsd... ever-node
ADNL... External... topic "requests" topics: "blocks", "accounts", "messages", "transactions"
topics:... Internal network (docker bridge)
Internal network (docker bridge) HTTPS endpoints: /graphql, /arangodb, /metrics
HTTPS endpoints:... Text is not SVG - cannot display
\ No newline at end of file
diff --git a/scripts/deploy.sh b/scripts/deploy.sh
deleted file mode 100755
index 11f5550..0000000
--- a/scripts/deploy.sh
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/bin/bash -eE
-
-SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)
-# shellcheck source=env.sh
-. "${SCRIPT_DIR}/env.sh"
-
-TMP_DIR=/tmp/$(basename "$0" .sh)_$$
-rm -rf "${TMP_DIR}"
-mkdir -p "${TMP_DIR}"
-
-set +eE
-
-for BUNDLE_COMPONENT in proxy web.root arangodb q-server kafka statsd ton-node; do
- if [ "${CLEAN_HOST}" = "yes" ]; then
- cd "${DOCKER_COMPOSE_DIR}/${BUNDLE_COMPONENT}/" && docker-compose down --volumes --remove-orphans
- else
- cd "${DOCKER_COMPOSE_DIR}/${BUNDLE_COMPONENT}/" && docker-compose stop
- fi
-done
-
-if [ "${CLEAN_HOST}" = "yes" ]; then
- docker system prune --all --force --volumes
- docker network create proxy_nw
-fi
-
-set -eE
-
-sed -i "s|yourdomain.com|${HOSTNAME}|g" "${DOCKER_COMPOSE_DIR}/arangodb/docker-compose.yml"
-sed -i "s|email for notification|${EMAIL_FOR_NOTIFICATIONS}|g" "${DOCKER_COMPOSE_DIR}/arangodb/docker-compose.yml"
-sed -i "s|NETWORK_TYPE.*|NETWORK_TYPE=${NETWORK_TYPE}|g" "${DOCKER_COMPOSE_DIR}/arangodb/.env"
-
-sed -i "s|host.yourdomain.com|${HOSTNAME}|g" "${DOCKER_COMPOSE_DIR}/web.root/.env"
-sed -i "s|host.yourdomain.com|${HOSTNAME}|g" "${DOCKER_COMPOSE_DIR}/web.root/index.html"
-sed -i "s|for notification|${EMAIL_FOR_NOTIFICATIONS}|g" "${DOCKER_COMPOSE_DIR}/web.root/docker-compose.yml"
-
-rm -f "${DOCKER_COMPOSE_DIR}/proxy/htpasswd/arango.yourdomain.com"
-echo "admin:\$apr1\$d0ifqbt3\$iayulpIOP2.IS4Sy1I2zJ0" >"${DOCKER_COMPOSE_DIR}/proxy/htpasswd/arango.${HOSTNAME}"
-echo "#iJJ9fWxb9Z6CS1aPagoW" >>"${DOCKER_COMPOSE_DIR}/proxy/htpasswd/arango.${HOSTNAME}"
-mv "${DOCKER_COMPOSE_DIR}/proxy/vhost.d/host.yourdomain.com" "${DOCKER_COMPOSE_DIR}/proxy/vhost.d/${HOSTNAME}"
-
-for BUNDLE_COMPONENT in proxy web.root arangodb; do
- cd "${DOCKER_COMPOSE_DIR}/${BUNDLE_COMPONENT}/" && docker-compose up -d
-done
-
-rm -rf "${DOCKER_COMPOSE_DIR}/q-server/build/ton-q-server"
-cd "${DOCKER_COMPOSE_DIR}/q-server/build" && git clone --recursive "${TON_Q_SERVER_GITHUB_REPO}"
-cd "${DOCKER_COMPOSE_DIR}/q-server/build/ton-q-server" && git checkout "${TON_Q_SERVER_GITHUB_COMMIT_ID}"
-cd "${DOCKER_COMPOSE_DIR}/q-server" && docker-compose up -d
-
-echo "INFO: Waiting for Kafka start..."
-cd "${DOCKER_COMPOSE_DIR}/kafka" || exit 1
-OK=0
-while [ $OK -ne 100 ]; do
- docker-compose up -d >"${TMP_DIR}/kafka.log" 2>&1
- OK=$(awk '
- BEGIN { fail = 0 }
- {
- if ($1 == "ERROR:") {
- fail = fail + 1
- }
- }
- END {
- if (fail != 0) {
- print 0
- } else {
- print 100
- }
- }
- ' "${TMP_DIR}/kafka.log")
-done
-rm -f "${TMP_DIR}/kafka.log"
-
-OK=0
-while [ $OK -ne 100 ]; do
- OK=$(docker ps --format 'table {{.Image}} \t {{.Names}} \t {{.Status}}' | awk '
- BEGIN { OK = 0 }
- {
- if (($2 == "check-connect") && ($3 == "Up")) {
- i = NF;
- if ($i == "(healthy)") {
- OK = OK + 1
- }
- }
- }
- END {
- if (OK != 1) {
- print OK
- } else {
- print 100
- }
- }
- ')
- sleep 1s
-done
-
-until [ "$(echo "${IntIP}" | grep "\." -o | wc -l)" -eq 3 ]; do
- set +e
- IntIP="$(curl -sS4 https://ip.me/)":${ADNL_PORT}
- set -e
- echo "INFO: IntIP = $IntIP"
- sleep 5s
-done
-sed -i "s|IntIP.*|IntIP=${IntIP}|g" "${DOCKER_COMPOSE_DIR}/statsd/.env"
-cd "${DOCKER_COMPOSE_DIR}/statsd/" && docker-compose up -d
-
-sed -i "s|ADNL_PORT.*|ADNL_PORT=${ADNL_PORT}|" "${DOCKER_COMPOSE_DIR}/ton-node/.env"
-sed -i "s|NETWORK_TYPE.*|NETWORK_TYPE=${NETWORK_TYPE}|" "${DOCKER_COMPOSE_DIR}/ton-node/.env"
-sed -i "s|NODE_CMD_1=.*|NODE_CMD_1=bash|g" "${DOCKER_COMPOSE_DIR}/ton-node/.env"
-
-rm -rf "${DOCKER_COMPOSE_DIR}/ton-node/build/ton-node"
-cd "${DOCKER_COMPOSE_DIR}/ton-node/build" && git clone --recursive "${TON_NODE_GITHUB_REPO}" ton-node
-cd "${DOCKER_COMPOSE_DIR}/ton-node/build/ton-node" && git checkout "${TON_NODE_GITHUB_COMMIT_ID}"
-
-rm -rf "${DOCKER_COMPOSE_DIR}/ton-node/build/ton-labs-node-tools"
-cd "${DOCKER_COMPOSE_DIR}/ton-node/build" && git clone --recursive "${TON_NODE_TOOLS_GITHUB_REPO}"
-cd "${DOCKER_COMPOSE_DIR}/ton-node/build/ton-labs-node-tools" && git checkout "${TON_NODE_TOOLS_GITHUB_COMMIT_ID}"
-
-echo "==============================================================================="
-echo "INFO: starting node on ${HOSTNAME}..."
-cd "${DOCKER_COMPOSE_DIR}/ton-node/" && docker-compose up -d
-docker exec --tty rnode "/ton-node/scripts/generate_console_config.sh"
-sed -i "s|NODE_CMD_1.*|NODE_CMD_1=normal|g" "${DOCKER_COMPOSE_DIR}/ton-node/.env"
-cd "${DOCKER_COMPOSE_DIR}/ton-node/" && docker-compose stop
-cd "${DOCKER_COMPOSE_DIR}/ton-node/" && docker-compose up -d
-echo "INFO: starting node on ${HOSTNAME}... DONE"
-echo "==============================================================================="
-
-docker ps -a
-rm -rf "${TMP_DIR}"
diff --git a/scripts/env.sh b/scripts/env.sh
deleted file mode 100755
index 28cf34a..0000000
--- a/scripts/env.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash -eE
-
-DEBUG=${DEBUG:-no}
-
-if [ "$DEBUG" = "yes" ]; then
- set -x
-fi
-
-SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)
-export SCRIPT_DIR
-SRC_TOP_DIR=$(cd "${SCRIPT_DIR}/../" && pwd -P)
-export SRC_TOP_DIR
-export DOCKER_COMPOSE_DIR="${SRC_TOP_DIR}/docker-compose"
-
-# Supported network types: net.ton.dev, main.ton.dev
-export NETWORK_TYPE="${NETWORK_TYPE:-net.ton.dev}"
-export CLEAN_HOST=${CLEAN_HOST:-yes}
-export ADNL_PORT=${ADNL_PORT:-30303}
-export EMAIL_FOR_NOTIFICATIONS="email@yourdomain.com"
-export COMPOSE_HTTP_TIMEOUT=120 # in sec, 60 sec - default
-HOSTNAME=$(hostname -f)
-export TON_Q_SERVER_GITHUB_REPO="https://github.com/tonlabs/ton-q-server"
-export TON_Q_SERVER_GITHUB_COMMIT_ID="0.54.0"
-export TON_NODE_GITHUB_REPO="https://github.com/tonlabs/ton-labs-node"
-export TON_NODE_GITHUB_COMMIT_ID="befb1ba4d91733ee2c14fa3cf4ebe8047b279e92"
-export TON_NODE_TOOLS_GITHUB_REPO="https://github.com/tonlabs/ton-labs-node-tools.git"
-export TON_NODE_TOOLS_GITHUB_COMMIT_ID="master"
diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh
deleted file mode 100755
index 70a9020..0000000
--- a/scripts/install_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash -eE
-
-echo "INFO: install dependencies..."
-sudo apt update
-sudo apt install -y \
- docker-compose \
- git
-echo "INFO: install dependencies... DONE"
diff --git a/docker-compose/arangodb/build/arango/config b/templates/arangodb/config
similarity index 78%
rename from docker-compose/arangodb/build/arango/config
rename to templates/arangodb/config
index dcdce18..454a87d 100644
--- a/docker-compose/arangodb/build/arango/config
+++ b/templates/arangodb/config
@@ -6,6 +6,12 @@
[database]
directory = /arango/db
+[frontend]
+proxy-request-check = false
+
+[web-interface]
+proxy-request-check = false
+
[server]
endpoint = tcp://[::]:8529
storage-engine = auto
@@ -41,15 +47,15 @@ output = +
[rocksdb]
# encryption-keyfile=/your-encryption-file
-# 30% RAM in bytes (total RAM: 23622320128 B or 22 GiB)
-block-cache-size = 7086696038
-# 30% RAM in bytes (total RAM: 23622320128 B or 22 GiB)
-total-write-buffer-size = 7086696038
+# 30% RAM in bytes (total RAM: 32 GiB)
+block-cache-size = 9830M
+# 30% RAM in bytes (total RAM: 32 GiB)
+total-write-buffer-size = 9830M
enforce-block-cache-size-limit = true
[query]
-memory-limit = 100000000
+memory-limit = 1000M
[cache]
-# 20% RAM in bytes (total RAM: 23622320128 B or 22 GiB)
-cache.size = 4724464025
+# 20% RAM in bytes (total RAM: 32 GiB)
+cache.size = 6553M
diff --git a/templates/arangodb/docker-compose.yml b/templates/arangodb/docker-compose.yml
new file mode 100644
index 0000000..ebd0c88
--- /dev/null
+++ b/templates/arangodb/docker-compose.yml
@@ -0,0 +1,25 @@
+version: '2.3'
+services:
+ arangodb:
+ image: arangodb:3.10.5
+ restart: unless-stopped
+ environment:
+ ARANGO_NO_AUTH: 1
+ ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY: {{ARANGO_MEMORY}}
+ networks:
+ - {{NETWORK}}
+ volumes:
+ - db3:/var/lib/arangodb3
+ - data:/arango/db
+ - ./config:/arango/config
+ - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
+ expose:
+ - "8529"
+ mem_limit: {{ARANGO_MEMORY}}
+
+networks:
+ {{NETWORK}}:
+ external: true
+volumes:
+ db3:
+ data:
diff --git a/docker-compose/arangodb/build/arango/initdb.d/upgrade-arango-db.js b/templates/arangodb/docker-entrypoint-initdb.d/upgrade.js
similarity index 100%
rename from docker-compose/arangodb/build/arango/initdb.d/upgrade-arango-db.js
rename to templates/arangodb/docker-entrypoint-initdb.d/upgrade.js
diff --git a/docker-compose/ton-node/build/Dockerfile b/templates/ever-node/build/Dockerfile
similarity index 91%
rename from docker-compose/ton-node/build/Dockerfile
rename to templates/ever-node/build/Dockerfile
index 5c80d4a..ee0e99c 100644
--- a/docker-compose/ton-node/build/Dockerfile
+++ b/templates/ever-node/build/Dockerfile
@@ -1,11 +1,11 @@
-ARG RUST_VERSION=1.61.0
+ARG RUST_VERSION=1.65.0
FROM ubuntu:18.04 as build
ARG RUST_VERSION
-COPY ton-node /tonlabs/ton-node/
-COPY ton-labs-node-tools /tonlabs/ton-labs-node-tools/
+COPY ever-node /tonlabs/ever-node/
+COPY ever-node-tools /tonlabs/ton-labs-node-tools/
# install deps
ENV TZ=Europe/Moscow
@@ -44,7 +44,7 @@ RUN curl https://packages.confluent.io/deb/5.5/archive.key | apt-key add;\
COPY rust_install.sh /tmp/rust_install.sh
RUN bash -c "/tmp/rust_install.sh ${RUST_VERSION}"
-WORKDIR /tonlabs/ton-node
+WORKDIR /tonlabs/ever-node
RUN cargo update && cargo build --release --features "external_db,metrics"
WORKDIR /tonlabs/ton-labs-node-tools
@@ -88,6 +88,7 @@ ENV ZSTD_LIB_DIR=/usr/lib/x86_64-linux-gnu
COPY rust_install.sh /tmp/rust_install.sh
RUN bash -c "/tmp/rust_install.sh ${RUST_VERSION}"
-COPY --from=build /tonlabs/ton-node/target/release/ton_node /ton-node/
-COPY --from=build /tonlabs/ton-labs-node-tools/target/release/console /ton-node/tools/
-COPY --from=build /tonlabs/ton-labs-node-tools/target/release/keygen /ton-node/tools/
+COPY --from=build /tonlabs/ever-node/target/release/ton_node /ever-node/
+COPY --from=build /tonlabs/ton-labs-node-tools/target/release/console /ever-node/tools/
+COPY --from=build /tonlabs/ton-labs-node-tools/target/release/keygen /ever-node/tools/
+
diff --git a/docker-compose/ton-node/build/rust_install.sh b/templates/ever-node/build/rust_install.sh
similarity index 100%
rename from docker-compose/ton-node/build/rust_install.sh
rename to templates/ever-node/build/rust_install.sh
diff --git a/docker-compose/ton-node/configs/console_template.json b/templates/ever-node/configs/console_template.json
similarity index 100%
rename from docker-compose/ton-node/configs/console_template.json
rename to templates/ever-node/configs/console_template.json
diff --git a/docker-compose/ton-node/configs/default_config.json b/templates/ever-node/configs/default_config.json
similarity index 97%
rename from docker-compose/ton-node/configs/default_config.json
rename to templates/ever-node/configs/default_config.json
index ed4a6ff..5e528ed 100644
--- a/docker-compose/ton-node/configs/default_config.json
+++ b/templates/ever-node/configs/default_config.json
@@ -24,7 +24,7 @@
"message_timeout_ms": 100,
"topic": "blocks",
"attempt_timeout_ms": 100,
- "message_max_size": 1000000
+ "message_max_size": 4000000
},
"message_producer": {
"enabled": true,
diff --git a/docker-compose/ton-node/configs/log_cfg.yml b/templates/ever-node/configs/log_cfg.yml
similarity index 93%
rename from docker-compose/ton-node/configs/log_cfg.yml
rename to templates/ever-node/configs/log_cfg.yml
index 19f6ca7..dc0e3ac 100644
--- a/docker-compose/ton-node/configs/log_cfg.yml
+++ b/templates/ever-node/configs/log_cfg.yml
@@ -15,13 +15,13 @@ appenders:
logfile:
kind: file
- path: "/ton-node/logs/output.log"
+ path: "/ever-node/logs/output.log"
encoder:
pattern: "{d(%s.%f)} {l} [{h({t})}] {I}: {m}{n}"
tvm_logfile:
kind: file
- path: "/ton-node/logs/tvm.log"
+ path: "/ever-node/logs/tvm.log"
encoder:
pattern: "{m}{n}"
@@ -94,4 +94,4 @@ loggers:
- stdout_ref
telemetry:
- level: debug
+ level: info
diff --git a/templates/ever-node/docker-compose.yml b/templates/ever-node/docker-compose.yml
new file mode 100644
index 0000000..d83e2ac
--- /dev/null
+++ b/templates/ever-node/docker-compose.yml
@@ -0,0 +1,39 @@
+version: '2.2'
+services:
+ node:
+ build:
+ context: ./build
+ container_name: ever-node
+ restart: unless-stopped
+ environment:
+ - ADNL_PORT={{ADNL_PORT}}
+ - VALIDATOR_NAME={{VALIDATOR_NAME}}
+ - NETWORK_TYPE={{NETWORK_TYPE}}
+ - CONFIGS_PATH=/ever-node/configs
+ - STATSD_DOMAIN=statsd
+ - STATSD_PORT=:9125 # here ":" is not a typo.
+ ports:
+ - {{ADNL_PORT}}:{{ADNL_PORT}}/udp
+ networks:
+ - {{NETWORK}}
+ volumes:
+ - ./configs/:/ever-node/configs/
+ - ./scripts/:/ever-node/scripts/
+ - ./logs/:/ever-node/logs/
+ - DB:/ever-node/node_db/
+ - /tmp/metrics/:/tmp/metrics/
+ entrypoint: /ever-node/scripts/entrypoint.sh
+ command: ["bash"]
+ mem_limit: {{NODE_MEMORY}}
+ logging:
+ driver: json-file
+ options:
+ max-size: "1000m"
+ max-file: "100"
+ cap_add:
+ - SYS_PTRACE
+networks:
+ {{NETWORK}}:
+ external: true
+volumes:
+ DB:
diff --git a/docker-compose/ton-node/logs/.placeholder b/templates/ever-node/logs/.keep
similarity index 100%
rename from docker-compose/ton-node/logs/.placeholder
rename to templates/ever-node/logs/.keep
diff --git a/docker-compose/ton-node/scripts/entrypoint.sh b/templates/ever-node/scripts/entrypoint.sh
similarity index 70%
rename from docker-compose/ton-node/scripts/entrypoint.sh
rename to templates/ever-node/scripts/entrypoint.sh
index 26a53ec..4f6b845 100755
--- a/docker-compose/ton-node/scripts/entrypoint.sh
+++ b/templates/ever-node/scripts/entrypoint.sh
@@ -1,6 +1,6 @@
#!/bin/bash -eEx
-echo "INFO: R-Node startup..."
+echo "INFO: ever-node startup..."
echo "INFO: NETWORK_TYPE = ${NETWORK_TYPE}"
echo "INFO: CONFIGS_PATH = ${CONFIGS_PATH}"
@@ -12,8 +12,8 @@ curl -sS "https://raw.githubusercontent.com/tonlabs/${NETWORK_TYPE}/master/confi
if [ "$1" = "bash" ]; then
tail -f /dev/null
else
- cd /ton-node
- exec /ton-node/ton_node --configs "${CONFIGS_PATH}"
+ cd /ever-node
+ exec /ever-node/ton_node --configs "${CONFIGS_PATH}"
fi
-echo "INFO: R-Node startup... DONE"
+echo "INFO: ever-node startup... DONE"
diff --git a/templates/ever-node/scripts/generate_console_config.sh b/templates/ever-node/scripts/generate_console_config.sh
new file mode 100755
index 0000000..cae91dd
--- /dev/null
+++ b/templates/ever-node/scripts/generate_console_config.sh
@@ -0,0 +1,48 @@
+#!/bin/bash -eEx
+
+if [ "$DEBUG" = "yes" ]; then
+ set -x
+fi
+
+EVER_NODE_ROOT_DIR="/ever-node"
+EVER_NODE_CONFIGS_DIR="${EVER_NODE_ROOT_DIR}/configs"
+EVER_NODE_TOOLS_DIR="${EVER_NODE_ROOT_DIR}/tools"
+EVER_NODE_CONSOLE_SERVER_PORT="3031"
+
+HOSTNAME=$(hostname -f)
+TMP_DIR="/tmp/$(basename "$0" .sh)_$$"
+rm -rf "${TMP_DIR}"
+mkdir -p "${TMP_DIR}"
+
+"${EVER_NODE_TOOLS_DIR}/keygen" >"${EVER_NODE_CONFIGS_DIR}/${HOSTNAME}_console_client_keys.json"
+cat "${EVER_NODE_CONFIGS_DIR}/${HOSTNAME}_console_client_keys.json"
+jq -c .public "${EVER_NODE_CONFIGS_DIR}/${HOSTNAME}_console_client_keys.json" >"${EVER_NODE_CONFIGS_DIR}/console_client_public.json"
+
+jq ".control_server_port = ${EVER_NODE_CONSOLE_SERVER_PORT}" "${EVER_NODE_CONFIGS_DIR}/default_config.json" >"${TMP_DIR}/default_config.json.tmp"
+cp "${TMP_DIR}/default_config.json.tmp" "${EVER_NODE_CONFIGS_DIR}/default_config.json"
+
+# Generate initial config.json
+cd "${EVER_NODE_ROOT_DIR}" && "${EVER_NODE_ROOT_DIR}/ton_node" --configs "${EVER_NODE_CONFIGS_DIR}" --ckey "$(cat "${EVER_NODE_CONFIGS_DIR}/console_client_public.json")" &
+
+# TODO: Why it's needed?
+sleep 60
+
+if [ ! -f "${EVER_NODE_CONFIGS_DIR}/config.json" ]; then
+ echo "ERROR: ${EVER_NODE_CONFIGS_DIR}/config.json does not exist"
+ exit 1
+fi
+
+cat "${EVER_NODE_CONFIGS_DIR}/config.json"
+
+if [ ! -f "${EVER_NODE_CONFIGS_DIR}/console_config.json" ]; then
+ echo "ERROR: ${EVER_NODE_CONFIGS_DIR}/console_config.json does not exist"
+ exit 1
+fi
+
+cat "${EVER_NODE_CONFIGS_DIR}/console_config.json"
+
+jq ".client_key = $(jq .private "${EVER_NODE_CONFIGS_DIR}/${HOSTNAME}_console_client_keys.json")" "${EVER_NODE_CONFIGS_DIR}/console_config.json" >"${TMP_DIR}/console_config.json.tmp"
+jq ".config = $(cat "${TMP_DIR}/console_config.json.tmp")" "${EVER_NODE_CONFIGS_DIR}/console_template.json" >"${EVER_NODE_CONFIGS_DIR}/console.json"
+rm -f "${EVER_NODE_CONFIGS_DIR}/console_config.json"
+
+rm -rf "${TMP_DIR}"
diff --git a/templates/ever-node/start_node.sh b/templates/ever-node/start_node.sh
new file mode 100755
index 0000000..56fef21
--- /dev/null
+++ b/templates/ever-node/start_node.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+cd deploy/ever-node
+rm -rf build/ever-node
+cd build && git clone --recursive {{EVERNODE_GITHUB_REPO}} ever-node
+cd ever-node && git checkout {{EVERNODE_GITHUB_COMMIT_ID}}
+cd ..
+rm -rf ever-node-tools
+git clone --recursive {{EVERNODE_TOOLS_GITHUB_REPO}}
+cd ever-node-tools && git checkout {{EVERNODE_TOOLS_GITHUB_COMMIT_ID}}
+cd ../../
+
+echo "==============================================================================="
+echo "INFO: starting node on {{HOSTNAME}}..."
+
+docker-compose up --build -d
+docker exec --tty ever-node "/ever-node/scripts/generate_console_config.sh"
+
+docker-compose down -t 300
+sed -i 's/"client_enabled":.*/"client_enabled": true,/' configs/config.json
+sed -i 's/"service_enabled":.*/"service_enabled": true/' configs/config.json
+sed -i 's/command: \["bash"\]/command: ["normal"]/' docker-compose.yml
+docker-compose up -d
+echo "INFO: starting node on {{HOSTNAME}}... DONE"
+echo "==============================================================================="
+
+docker ps -a
diff --git a/templates/kafka/build_check/Dockerfile b/templates/kafka/build_check/Dockerfile
new file mode 100644
index 0000000..7bab3d1
--- /dev/null
+++ b/templates/kafka/build_check/Dockerfile
@@ -0,0 +1,8 @@
+FROM confluentinc/cp-kafka-connect:7.3.3-1-ubi8.amd64
+USER root
+RUN microdnf update
+RUN microdnf install jq findutils
+COPY check.sh /work/check.sh
+COPY /connectors/ /work/connectors/
+COPY entrypoint.sh /entrypoint.sh
+ENTRYPOINT ["/entrypoint.sh"]
diff --git a/templates/kafka/build_check/check.sh b/templates/kafka/build_check/check.sh
new file mode 100755
index 0000000..15cdea9
--- /dev/null
+++ b/templates/kafka/build_check/check.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env sh
+
+ENDPOINT=$1
+
+# List current connectors and status
+curl -s $ENDPOINT | \
+ jq '.[]'| sed -e 's/"//g' | \
+ xargs -I{connector_name} curl -s "$ENDPOINT/{connector_name}/status"| \
+ jq -c -M '[.name,.connector.state,.tasks[].state]|join(":|:")'| column -s : -t| sed 's/\"//g'| sort | tee /work/result.txt
+
+# Restart any connector tasks that are FAILED
+curl -s $ENDPOINT | \
+ jq '.[]' | sed -e 's/"//g' | \
+ xargs -I{connector_name} curl -s "$ENDPOINT/{connector_name}/status" | \
+ jq -c -M '[select(.tasks[].state=="FAILED") | .name,"§±§",.tasks[].id]' | \
+ grep -v "\[\]"| \
+ sed -e 's/^\[\"//g'| sed -e 's/\",\"§±§\",/\/tasks\//g'|sed -e 's/\]$//g'| \
+ xargs -I{connector_and_task} curl -v -X POST "$ENDPOINT/{connector_and_task}/restart"
+
+# put error status
+grep "FAILED" -qs /work/result.txt && exit 1 || exit 0
diff --git a/templates/kafka/build_check/connectors/arangodb-accounts-sink.json b/templates/kafka/build_check/connectors/arangodb-accounts-sink.json
new file mode 100644
index 0000000..48a57a0
--- /dev/null
+++ b/templates/kafka/build_check/connectors/arangodb-accounts-sink.json
@@ -0,0 +1,19 @@
+{
+ "name": "arangodb-accounts-sink",
+ "config": {
+ "connector.class": "io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector",
+ "tasks.max": "1",
+ "topics": "accounts",
+ "arangodb.host": "arangodb",
+ "arangodb.port": "8529",
+ "arangodb.user": "root",
+ "arangodb.database.name": "blockchain",
+ "transforms": "KeyTransform",
+ "transforms.KeyTransform.field": "id",
+ "transforms.KeyTransform.type": "org.apache.kafka.connect.transforms.HoistField$Key",
+ "key.converter.schemas.enable": "false",
+ "key.converter": "org.apache.kafka.connect.json.JsonConverter",
+ "value.converter.schemas.enable": "false",
+ "value.converter": "org.apache.kafka.connect.json.JsonConverter"
+ }
+}
diff --git a/templates/kafka/build_check/connectors/arangodb-blocks-signatures-sink.json b/templates/kafka/build_check/connectors/arangodb-blocks-signatures-sink.json
new file mode 100644
index 0000000..f3d1991
--- /dev/null
+++ b/templates/kafka/build_check/connectors/arangodb-blocks-signatures-sink.json
@@ -0,0 +1,19 @@
+{
+ "name": "arangodb-blocks-signatures-sink",
+ "config": {
+ "connector.class": "io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector",
+ "tasks.max": "1",
+ "topics": "blocks_signatures",
+ "arangodb.host": "arangodb",
+ "arangodb.port": "8529",
+ "arangodb.user": "root",
+ "arangodb.database.name": "blockchain",
+ "transforms": "KeyTransform",
+ "transforms.KeyTransform.field": "id",
+ "transforms.KeyTransform.type": "org.apache.kafka.connect.transforms.HoistField$Key",
+ "key.converter.schemas.enable": "false",
+ "key.converter": "org.apache.kafka.connect.json.JsonConverter",
+ "value.converter.schemas.enable": "false",
+ "value.converter": "org.apache.kafka.connect.json.JsonConverter"
+ }
+}
diff --git a/templates/kafka/build_check/connectors/arangodb-blocks-sink.json b/templates/kafka/build_check/connectors/arangodb-blocks-sink.json
new file mode 100644
index 0000000..71086a4
--- /dev/null
+++ b/templates/kafka/build_check/connectors/arangodb-blocks-sink.json
@@ -0,0 +1,19 @@
+{
+ "name": "arangodb-blocks-sink",
+ "config": {
+ "connector.class": "io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector",
+ "tasks.max": "1",
+ "topics": "blocks",
+ "arangodb.host":"arangodb",
+ "arangodb.port": "8529",
+ "arangodb.user": "root",
+ "arangodb.database.name": "blockchain",
+ "transforms": "KeyTransform",
+ "transforms.KeyTransform.field": "id",
+ "transforms.KeyTransform.type": "org.apache.kafka.connect.transforms.HoistField$Key",
+ "key.converter.schemas.enable": "false",
+ "key.converter": "org.apache.kafka.connect.json.JsonConverter",
+ "value.converter.schemas.enable": "false",
+ "value.converter": "org.apache.kafka.connect.json.JsonConverter"
+ }
+}
diff --git a/templates/kafka/build_check/connectors/arangodb-messages-sink.json b/templates/kafka/build_check/connectors/arangodb-messages-sink.json
new file mode 100644
index 0000000..439a539
--- /dev/null
+++ b/templates/kafka/build_check/connectors/arangodb-messages-sink.json
@@ -0,0 +1,20 @@
+{
+ "name": "arangodb-messages-sink",
+ "config": {
+ "connector.class": "io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector",
+ "tasks.max": "1",
+ "topics": "messages",
+ "arangodb.host":"arangodb",
+ "arangodb.port": "8529",
+ "arangodb.user": "root",
+ "arangodb.database.name": "blockchain",
+ "arangodb.insert.overwritemode": "update",
+ "transforms": "KeyTransform",
+ "transforms.KeyTransform.field": "id",
+ "transforms.KeyTransform.type": "org.apache.kafka.connect.transforms.HoistField$Key",
+ "key.converter.schemas.enable": "false",
+ "key.converter": "org.apache.kafka.connect.json.JsonConverter",
+ "value.converter.schemas.enable": "false",
+ "value.converter": "org.apache.kafka.connect.json.JsonConverter"
+ }
+}
diff --git a/templates/kafka/build_check/connectors/arangodb-transactions-sink.json b/templates/kafka/build_check/connectors/arangodb-transactions-sink.json
new file mode 100644
index 0000000..e2b76a0
--- /dev/null
+++ b/templates/kafka/build_check/connectors/arangodb-transactions-sink.json
@@ -0,0 +1,19 @@
+{
+ "name": "arangodb-transactions-sink",
+ "config": {
+ "connector.class": "io.github.jaredpetersen.kafkaconnectarangodb.sink.ArangoDbSinkConnector",
+ "tasks.max": "1",
+ "topics": "transactions",
+ "arangodb.host":"arangodb",
+ "arangodb.port": "8529",
+ "arangodb.user": "root",
+ "arangodb.database.name": "blockchain",
+ "transforms": "KeyTransform",
+ "transforms.KeyTransform.field": "id",
+ "transforms.KeyTransform.type": "org.apache.kafka.connect.transforms.HoistField$Key",
+ "key.converter.schemas.enable": "false",
+ "key.converter": "org.apache.kafka.connect.json.JsonConverter",
+ "value.converter.schemas.enable": "false",
+ "value.converter": "org.apache.kafka.connect.json.JsonConverter"
+ }
+}
diff --git a/templates/kafka/build_check/entrypoint.sh b/templates/kafka/build_check/entrypoint.sh
new file mode 100755
index 0000000..dd92b97
--- /dev/null
+++ b/templates/kafka/build_check/entrypoint.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+#
+# Create topics
+#
+set -e pipefail
+
+kafka-topics --create --bootstrap-server kafka:29092 --topic accounts --replication-factor 1 --partitions 20 --if-not-exists
+# sleep 2 ????? WHY?
+kafka-topics --create --bootstrap-server kafka:29092 --topic transactions --replication-factor 1 --partitions 40 --if-not-exists
+# sleep 2 ????? WHY?
+kafka-topics --create --bootstrap-server kafka:29092 --topic blocks --replication-factor 1 --partitions 5 --if-not-exists
+# sleep 2 ????? WHY?
+kafka-topics --create --bootstrap-server kafka:29092 --topic messages --replication-factor 1 --partitions 60 --if-not-exists
+# sleep 2 ????? WHY?
+kafka-topics --create --bootstrap-server kafka:29092 --topic requests --replication-factor 1 --partitions 30 --if-not-exists
+# sleep 2 ????? WHY?
+kafka-topics --create --bootstrap-server kafka:29092 --topic blocks_signatures --replication-factor 1 --partitions 5 --if-not-exists
+
+###
+# TODO Why we want to change just created topics ?
+#
+# kafka-topics --alter --bootstrap-server kafka:29092 --topic accounts --partitions 20 --if-exists
+# kafka-topics --alter --bootstrap-server kafka:29092 --topic transactions --partitions 40 --if-exists
+# kafka-topics --alter --bootstrap-server kafka:29092 --topic blocks --partitions 5 --if-exists
+# kafka-topics --alter --bootstrap-server kafka:29092 --topic messages --partitions 60 --if-exists
+# kafka-topics --alter --bootstrap-server kafka:29092 --topic requests --partitions 30 --if-exists
+# kafka-topics --alter --bootstrap-server kafka:29092 --topic blocks_signatures --partitions 55 --if-exists
+set -e pipefail
+for connector in $(ls /work/connectors/*.json); do
+ curl \
+ --max-time 5 -i \
+ -X POST -H "Accept:application/json" \
+ -H "Content-Type:application/json" connect:8083/connectors/ -d @/${connector}
+ sleep 10s
+done
+
+exec tail -f /dev/null
+
diff --git a/docker-compose/kafka/docker-compose.yml b/templates/kafka/docker-compose.yml
similarity index 72%
rename from docker-compose/kafka/docker-compose.yml
rename to templates/kafka/docker-compose.yml
index ce50b07..49e1791 100644
--- a/docker-compose/kafka/docker-compose.yml
+++ b/templates/kafka/docker-compose.yml
@@ -1,35 +1,36 @@
version: '2.3'
services:
zookeeper:
- image: confluentinc/cp-zookeeper:5.3.1
- container_name: zookeeper
+ image: confluentinc/cp-zookeeper:7.3.3-1-ubi8.amd64
restart: unless-stopped
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
networks:
- - proxy_nw
+ - {{NETWORK}}
healthcheck:
test: ["CMD-SHELL", "echo ruok | nc -w 2 zookeeper 2181"]
interval: 60s
timeout: 5s
retries: 3
start_period: 40s
+ volumes:
+ - zk_data:/var/lib/zookeeper/data
+ - zk_log:/var/lib/zookeeper/log
kafka:
- image: confluentinc/cp-kafka:5.3.1
- container_name: kafka
+ image: confluentinc/cp-kafka:7.3.3-1-ubi8.amd64
restart: unless-stopped
depends_on:
- zookeeper
expose:
- "9092"
networks:
- - proxy_nw
+ - {{NETWORK}}
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
- KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://${ADVERTISED_LISTENER}:9092
+ KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://kafka:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
@@ -45,14 +46,13 @@ services:
KAFKA_REPLICA_FETCH_MAX_BYTES: 4000000
volumes:
- data:/var/lib/kafka/data
+ mem_limit: {{KAFKA_MEMORY}}
connect:
- image: confluentinc/cp-kafka-connect:5.3.1
- container_name: connect
+ image: confluentinc/cp-kafka-connect:7.3.3-1-ubi8.amd64
restart: unless-stopped
depends_on:
- zookeeper
- kafka
- - schema-registry
environment:
CONNECT_BOOTSTRAP_SERVERS: 'kafka:29092'
CONNECT_REST_ADVERTISED_HOST_NAME: connect
@@ -66,8 +66,7 @@ services:
CONNECT_STATUS_STORAGE_TOPIC: docker-connect-status
CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: 1
CONNECT_KEY_CONVERTER: org.apache.kafka.connect.storage.StringConverter
- CONNECT_VALUE_CONVERTER: io.confluent.connect.avro.AvroConverter
- CONNECT_VALUE_CONVERTER_SCHEMA_REGISTRY_URL: http://schema-registry:8081
+ CONNECT_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
CONNECT_INTERNAL_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
CONNECT_INTERNAL_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
CONNECT_ZOOKEEPER_CONNECT: 'zookeeper:2181'
@@ -78,11 +77,12 @@ services:
CONNECT_PLUGIN_PATH: "/usr/share/java,/usr/share/confluent-hub-components"
CONNECT_LOG4J_LOGGERS: org.apache.zookeeper=ERROR,org.I0Itec.zkclient=ERROR,org.reflections=ERROR
KAFKA_JMX_PORT: 9584
- CONNECT_FETCH_MESSAGE_MAX_BYTES: 3001000
- CONNECT_MAX_REQUEST_SIZE: 3001000
- CONNECT_MAX_PARTITION_FETCH_BYTES: 3001000
+ CONNECT_FETCH_MESSAGE_MAX_BYTES: 4001000
+ CONNECT_MAX_REQUEST_SIZE: 4001000
+ # https://docs.confluent.io/platform/7.3/installation/configuration/consumer-configs.html#fetch-max-bytes
+ CONNECT_MAX_PARTITION_FETCH_BYTES: 4001000
networks:
- - proxy_nw
+ - {{NETWORK}}
volumes:
- ./files/kafka-connect-arangodb:/usr/share/java/kafka-connect-arangodb
healthcheck:
@@ -91,51 +91,29 @@ services:
timeout: 5s
retries: 3
start_period: 60s
- mem_limit: 30G
-
- schema-registry:
- image: confluentinc/cp-schema-registry:5.3.1
- hostname: schema-registry
- container_name: schema-registry
- restart: unless-stopped
- depends_on:
- - zookeeper
- - kafka
- expose:
- - 8081
- environment:
- SCHEMA_REGISTRY_HOST_NAME: schema-registry
- SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
- SCHEMA_REGISTRY_JMX_PORT: 9582
- networks:
- - proxy_nw
-
-
- networks:
- - proxy_nw
- volumes:
- - ./launch.sh:/etc/confluent/docker/launch
+ mem_limit: {{CONNECT_MEMORY}}
check-connect:
build:
context: build_check
- container_name: check-connect
restart: unless-stopped
depends_on:
connect:
condition: service_healthy
healthcheck:
- test: ["CMD-SHELL", "/work/check.sh connect"]
+ test: ["CMD-SHELL", "/work/check.sh http://connect:8083/connectors"]
interval: 60s
timeout: 5s
retries: 3
start_period: 120s
networks:
- - proxy_nw
+ - {{NETWORK}}
networks:
- proxy_nw:
+ {{NETWORK}}:
external: true
volumes:
data:
+ zk_log:
+ zk_data:
diff --git a/docker-compose/kafka/files/kafka-connect-arangodb/LICENSE.md b/templates/kafka/files/kafka-connect-arangodb/LICENSE.md
similarity index 100%
rename from docker-compose/kafka/files/kafka-connect-arangodb/LICENSE.md
rename to templates/kafka/files/kafka-connect-arangodb/LICENSE.md
diff --git a/docker-compose/kafka/files/kafka-connect-arangodb/README.md b/templates/kafka/files/kafka-connect-arangodb/README.md
similarity index 100%
rename from docker-compose/kafka/files/kafka-connect-arangodb/README.md
rename to templates/kafka/files/kafka-connect-arangodb/README.md
diff --git a/docker-compose/kafka/files/kafka-connect-arangodb/arangodb-avocado-logo.png b/templates/kafka/files/kafka-connect-arangodb/arangodb-avocado-logo.png
similarity index 100%
rename from docker-compose/kafka/files/kafka-connect-arangodb/arangodb-avocado-logo.png
rename to templates/kafka/files/kafka-connect-arangodb/arangodb-avocado-logo.png
diff --git a/docker-compose/kafka/files/kafka-connect-arangodb/jackson-core-2.9.8.jar b/templates/kafka/files/kafka-connect-arangodb/jackson-core-2.9.8.jar
similarity index 100%
rename from docker-compose/kafka/files/kafka-connect-arangodb/jackson-core-2.9.8.jar
rename to templates/kafka/files/kafka-connect-arangodb/jackson-core-2.9.8.jar
diff --git a/docker-compose/kafka/files/kafka-connect-arangodb/kafka-connect-arangodb-1.0.8.jar b/templates/kafka/files/kafka-connect-arangodb/kafka-connect-arangodb-1.0.8.jar
similarity index 100%
rename from docker-compose/kafka/files/kafka-connect-arangodb/kafka-connect-arangodb-1.0.8.jar
rename to templates/kafka/files/kafka-connect-arangodb/kafka-connect-arangodb-1.0.8.jar
diff --git a/docker-compose/kafka/files/kafka-connect-arangodb/slf4j-api-1.7.13.jar b/templates/kafka/files/kafka-connect-arangodb/slf4j-api-1.7.13.jar
similarity index 100%
rename from docker-compose/kafka/files/kafka-connect-arangodb/slf4j-api-1.7.13.jar
rename to templates/kafka/files/kafka-connect-arangodb/slf4j-api-1.7.13.jar
diff --git a/docker-compose/kafka/files/kafka-connect-arangodb/velocypack-1.4.1.jar b/templates/kafka/files/kafka-connect-arangodb/velocypack-1.4.1.jar
similarity index 100%
rename from docker-compose/kafka/files/kafka-connect-arangodb/velocypack-1.4.1.jar
rename to templates/kafka/files/kafka-connect-arangodb/velocypack-1.4.1.jar
diff --git a/docker-compose/proxy/docker-compose.yml b/templates/proxy/docker-compose.yml
similarity index 53%
rename from docker-compose/proxy/docker-compose.yml
rename to templates/proxy/docker-compose.yml
index bb97928..371ea98 100644
--- a/docker-compose/proxy/docker-compose.yml
+++ b/templates/proxy/docker-compose.yml
@@ -1,10 +1,10 @@
version: '2.3'
services:
proxy:
- build:
- context: ./build
- # image: jwilder/nginx-proxy:latest
- container_name: proxy
+ image: jwilder/nginx-proxy:0.8.0
+ # build:
+ # context: ./build
+# container_name: proxy
restart: unless-stopped
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
@@ -14,14 +14,14 @@ services:
- "80:80"
- "443:443"
networks:
- - nw
+ - {{NETWORK}}
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- - /etc/ssl/docker:/etc/nginx/certs
+ - ./certs:/etc/nginx/certs
- ./vhost.d:/etc/nginx/vhost.d
- - /usr/share/nginx/html
+ - ./html:/usr/share/nginx/html
- ./proxy-settings.conf:/etc/nginx/conf.d/proxy-settings.conf
- - ./htpasswd:/etc/nginx/htpasswd
+ - ./.htpasswd:/etc/nginx/.htpasswd
healthcheck:
test: grep -q -e 00000000:0050 -e 00000000:01BB /proc/net/tcp
interval: 1m30s
@@ -30,17 +30,30 @@ services:
start_period: 40s
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion:v1.12
- container_name: letsencrypt
+# container_name: letsencrypt
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- - /etc/ssl/docker:/etc/nginx/certs:rw
networks:
- - nw
+ - {{NETWORK}}
volumes_from:
- proxy
+ web.root:
+ image: nginx:1.13.12
+# container_name: web.root
+ restart: unless-stopped
+ environment:
+ - VIRTUAL_HOST={{EVERNODE_FQDN}}
+ - LETSENCRYPT_HOST={{EVERNODE_FQDN}}
+ - LETSENCRYPT_EMAIL={{LETSENCRYPT_EMAIL}}
+ networks:
+ - {{NETWORK}}
+ volumes:
+ - ./index.html:/usr/share/nginx/html/index.html
+ expose:
+ - "80"
networks:
- nw:
- driver: bridge
+ {{NETWORK}}:
+ external: true
diff --git a/templates/proxy/index.html b/templates/proxy/index.html
new file mode 100644
index 0000000..63d550c
--- /dev/null
+++ b/templates/proxy/index.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/docker-compose/proxy/proxy-settings.conf b/templates/proxy/proxy-settings.conf
similarity index 100%
rename from docker-compose/proxy/proxy-settings.conf
rename to templates/proxy/proxy-settings.conf
diff --git a/docker-compose/proxy/vhost.d/default b/templates/proxy/vhost.d/default
similarity index 100%
rename from docker-compose/proxy/vhost.d/default
rename to templates/proxy/vhost.d/default
diff --git a/docker-compose/proxy/vhost.d/host.yourdomain.com b/templates/proxy/vhost.d/host.yourdomain.com
similarity index 52%
rename from docker-compose/proxy/vhost.d/host.yourdomain.com
rename to templates/proxy/vhost.d/host.yourdomain.com
index 8c3d965..d2421c5 100644
--- a/docker-compose/proxy/vhost.d/host.yourdomain.com
+++ b/templates/proxy/vhost.d/host.yourdomain.com
@@ -20,3 +20,24 @@ location /graphql {
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
}
+location /arangodb {
+ auth_basic "Restricted Content";
+ auth_basic_user_file /etc/nginx/.htpasswd;
+ proxy_pass http://arangodb:8529/;
+ proxy_set_header X-Script-Name /arangodb;
+}
+
+location /_db {
+ auth_basic "Restricted Content";
+ auth_basic_user_file /etc/nginx/.htpasswd;
+ proxy_pass http://arangodb:8529/_db;
+ proxy_set_header X-Script-Name /arangodb;
+}
+
+location /metrics {
+ proxy_http_version 1.1;
+ proxy_pass http://statsd:9102/metrics;
+ proxy_set_header Host $host;
+ proxy_read_timeout 7200;
+ proxy_buffering off;
+}
diff --git a/templates/q-server/build/Dockerfile b/templates/q-server/build/Dockerfile
new file mode 100644
index 0000000..54397e3
--- /dev/null
+++ b/templates/q-server/build/Dockerfile
@@ -0,0 +1,8 @@
+FROM node:18-buster
+USER node
+WORKDIR /home/node
+USER node
+COPY ton-q-server /home/node/
+RUN npm ci && npm run tsc && npm ci --production
+EXPOSE 4000
+ENTRYPOINT ["node", "index.js"]
diff --git a/templates/q-server/docker-compose.yml b/templates/q-server/docker-compose.yml
new file mode 100644
index 0000000..f753624
--- /dev/null
+++ b/templates/q-server/docker-compose.yml
@@ -0,0 +1,25 @@
+version: '2.3'
+services:
+ q-server:
+ build:
+ context: ./build
+ restart: unless-stopped
+ environment:
+ - VIRTUAL_HOST=q-server
+ - VIRTUAL_PORT=4000
+ - Q_DATA_MUT=http://arangodb:8529
+ - Q_DATA_HOT=http://arangodb:8529
+ - Q_REQUESTS_MODE=kafka
+ - Q_REQUESTS_SERVER=kafka:9092
+ - Q_REQUESTS_TOPIC=requests
+ - Q_QUERY_MAX_RUNTIME=60
+ - Q_SLOW_QUERIES=enable
+
+ networks:
+ - {{NETWORK}}
+ expose:
+ - "4000"
+ mem_limit: {{QSERVER_MEMORY}}
+networks:
+ {{NETWORK}}:
+ external: true
diff --git a/templates/statsd/docker-compose.yml b/templates/statsd/docker-compose.yml
new file mode 100644
index 0000000..5c8c442
--- /dev/null
+++ b/templates/statsd/docker-compose.yml
@@ -0,0 +1,21 @@
+version: '2.3'
+services:
+ statsd:
+ image: prom/statsd-exporter:v0.12.2
+ restart: unless-stopped
+ expose:
+ - "9125/udp"
+ - "9102/tcp"
+ networks:
+ - {{NETWORK}}
+ volumes:
+ - ./mapping:/statsd-mappings/statsd-mapping.yml
+ command: [--statsd.mapping-config=/statsd-mappings/statsd-mapping.yml]
+ logging:
+ driver: json-file
+ options:
+ max-size: "100m"
+ max-file: "10"
+networks:
+ {{NETWORK}}:
+ external: true
diff --git a/docker-compose/statsd/statsd-mapping.yaml b/templates/statsd/mapping
similarity index 100%
rename from docker-compose/statsd/statsd-mapping.yaml
rename to templates/statsd/mapping
diff --git a/templates/templater.sh b/templates/templater.sh
new file mode 100755
index 0000000..c972e42
--- /dev/null
+++ b/templates/templater.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+# Replaces all {{VAR}} by the $VAR value in a template file and outputs it
+# Use with -h to output all variables
+#
+# https://github.com/lavoiesl/bash-templater/blob/master/templater.sh
+#
+
+if [[ ! -f "$1" ]]; then
+ echo "Usage: VAR=value $0 template" >&2
+ exit 1
+fi
+
+template="$1"
+vars=$(grep -oE '\{\{\s*[A-Za-z0-9_]+\s*\}\}' "$template" | sort | uniq | sed -e 's/^{{//' -e 's/}}$//')
+
+if [[ -z "$vars" ]]; then
+ echo "Warning: No variable was found in $template, syntax is {{VAR}}" >&2
+fi
+
+var_value() {
+ var="${1}"
+ eval echo \$"${var}"
+}
+
+##
+# Escape custom characters in a string
+# Example: escape "ab'\c" '\' "'" ===> ab\'\\c
+#
+function escape_chars() {
+ local content="${1}"
+ shift
+
+ for char in "$@"; do
+ content="${content//${char}/\\${char}}"
+ done
+
+ echo "${content}"
+}
+
+function echo_var() {
+ local var="${1}"
+ local content="${2}"
+ local escaped="$(escape_chars "${content}" "\\" '"')"
+
+ echo "${var}=\"${escaped}\""
+}
+
+declare -a replaces
+replaces=()
+
+# Reads default values defined as {{VAR=value}} and delete those lines
+# There are evaluated, so you can do {{PATH=$HOME}} or {{PATH=`pwd`}}
+# You can even reference variables defined in the template before
+defaults=$(grep -oE '^\{\{[A-Za-z0-9_]+=.+\}\}$' "${template}" | sed -e 's/^{{//' -e 's/}}$//')
+IFS=$'\n'
+for default in $defaults; do
+ var=$(echo "${default}" | grep -oE "^[A-Za-z0-9_]+")
+ current="$(var_value "${var}")"
+
+ # Replace only if var is not set
+ if [[ -n "$current" ]]; then
+ eval "$(echo_var "${var}" "${current}")"
+ else
+ eval "${default}"
+ fi
+
+ # remove define line
+ replaces+=("-e")
+ replaces+=("/^{{${var}=/d")
+ vars="${vars} ${var}"
+done
+
+vars="$(echo "${vars}" | tr " " "\n" | sort | uniq)"
+
+if [[ "$2" = "-h" ]]; then
+ for var in $vars; do
+ value="$(var_value "${var}")"
+ echo_var "${var}" "${value}"
+ done
+ exit 0
+fi
+
+# Replace all {{VAR}} by $VAR value
+for var in $vars; do
+ value="$(var_value "${var}")"
+ if [[ -z "$value" ]]; then
+ echo "Warning: $var is not defined and no default is set, replacing by empty" >&2
+ fi
+
+ # Escape slashes
+ value="$(escape_chars "${value}" "\\" '/' ' ')";
+ replaces+=("-e")
+ replaces+=("s/{{\s*${var}\s*}}/${value}/g")
+done
+
+sed -i "${replaces[@]}" "${template}"
diff --git a/tests/.editorconfig b/tests/.editorconfig
new file mode 100644
index 0000000..3c44241
--- /dev/null
+++ b/tests/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
diff --git a/tests/.eslintrc.json b/tests/.eslintrc.json
new file mode 100644
index 0000000..3abfd60
--- /dev/null
+++ b/tests/.eslintrc.json
@@ -0,0 +1,20 @@
+{
+ "env": {
+ "es2021": true,
+ "node": true
+ },
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": 12,
+ "sourceType": "module"
+ },
+ "plugins": [
+ "@typescript-eslint"
+ ],
+ "rules": {
+ }
+}
diff --git a/tests/.prettierrc b/tests/.prettierrc
new file mode 100644
index 0000000..644d452
--- /dev/null
+++ b/tests/.prettierrc
@@ -0,0 +1,14 @@
+{
+ "trailingComma": "all",
+ "tabWidth": 4,
+ "semi": false,
+ "singleQuote": false,
+ "printWidth": 80,
+ "arrowParens": "avoid",
+ "bracketSpacing": true,
+ "endOfLine": "lf",
+ "proseWrap": "preserve",
+ "quoteProps": "as-needed",
+ "requirePragma": false,
+ "useTabs": false
+}
diff --git a/tests/.vscode/extensions.json b/tests/.vscode/extensions.json
new file mode 100644
index 0000000..8ccf0e7
--- /dev/null
+++ b/tests/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["dbaeumer.vscode-eslint"]
+}
diff --git a/tests/.vscode/settings.json b/tests/.vscode/settings.json
new file mode 100644
index 0000000..1c6c7f4
--- /dev/null
+++ b/tests/.vscode/settings.json
@@ -0,0 +1,25 @@
+{
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "eslint.enable": true,
+ "eslint.validate": ["javascript", "typescript"],
+ "editor.formatOnSave": true,
+ "[javascript]": {
+ "editor.formatOnSave": false
+ },
+ "[typescript]": {
+ "editor.defaultFormatter": "vscode.typescript-language-features",
+ "editor.formatOnSave": true,
+ "editor.formatOnPaste": false
+ },
+ "[markdown]": {
+ "editor.formatOnSave": true
+ },
+ "search.exclude": {
+ "**/node_modules": true,
+ "**/bower_components": true,
+ "**/dist": true,
+ "**/coverage": true
+ }
+}
diff --git a/tests/.vscode/tasks.json b/tests/.vscode/tasks.json
new file mode 100644
index 0000000..f8da75c
--- /dev/null
+++ b/tests/.vscode/tasks.json
@@ -0,0 +1,22 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "type": "npm",
+ "script": "build",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ },
+ {
+ "type": "npm",
+ "script": "start",
+ "problemMatcher": [],
+ "label": "npm: start",
+ "detail": "npm run start"
+ }
+ ]
+}
diff --git a/tests/Dockerfile b/tests/Dockerfile
new file mode 100644
index 0000000..8be567b
--- /dev/null
+++ b/tests/Dockerfile
@@ -0,0 +1,6 @@
+FROM node:18-buster
+WORKDIR /home/node
+USER node
+COPY . /home/node/
+RUN npm install
+ENTRYPOINT ["npm", "run", "msig-wallet"]
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 0000000..ded8a50
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,45 @@
+# Examples of working with multisig wallet, querying and subscribing.
+
+## Prerequisites
+
+Create a project at https://dashboard.evercloud.dev and export the API endpoint as an environment variable:
+```
+export ENDPOINT=https://devnet.evercloud.dev//graphql
+```
+
+## Work with wallet
+
+This script:
+- Generates a key pair for the wallet to be deployed.
+- Calculates future wallet address.
+- Waits for account replenishment.
+- Deploys multisig wallet.
+- Transfers 0.5 tokens from the wallet to some account.
+- Lists all made transactions.
+
+### Run this script
+
+During this test you need to send 1 token to the specified account.\
+You can topup your wallet from dashboard at https://dashboard.evercloud.dev
+
+```
+npm i
+npm run msig-wallet
+```
+### Example output
+```
+Generated wallet keys: {
+ "public":"c3044c02c49e9249fc0e3969e6f1eafa8b9f1caa0a38b867146f64216e904a34","secret":"3d3985b24f65099e811d4183e39581f2866d9cb7a53cb1f43f0fae8359002b7c"}
+Do not forget to save the keys!
+You can topup your wallet from dashboard at https://dashboard.evercloud.dev
+Please send >= 1 tokens to 0:1bbe56f5a95eafb7a747afd97a4815e8555a3d0aa595a4f3e2f9d1aa196d6b75
+awaiting...
+Account balance is: 100 tokens
+Deploying wallet contract to address: 0:1bbe56f5a95eafb7a747afd97a4815e8555a3d0aa595a4f3e2f9d1aa196d6b75 and waiting for transaction...
+Contract deployed. Transaction id 0b7675a425ec02b119d215fde78f28d88351e816b1de4172541277b22d5b7990
+Sending 0.5 token to -1:3333333333333333333333333333333333333333333333333333333333333333
+Transfer completed. Transaction id 5e844dfa6c3d0b580eeb5b8827d32f0b0b0e7ffeeffacdf907cb1f2657990c62
+Transaction id: transaction/ed500bae44b4441e3aa5bb6da1a07339d9d70adbd0c04a603ad16ab19b583727
+Transaction id: transaction/0b7675a425ec02b119d215fde78f28d88351e816b1de4172541277b22d5b7990
+Transaction id: transaction/5e844dfa6c3d0b580eeb5b8827d32f0b0b0e7ffeeffacdf907cb1f2657990c62
+```
\ No newline at end of file
diff --git a/tests/contract/README.txt b/tests/contract/README.txt
new file mode 100644
index 0000000..78d91e7
--- /dev/null
+++ b/tests/contract/README.txt
@@ -0,0 +1,3 @@
+https://github.com/EverSurf/contracts/blob/main/multisig2/SetcodeMultisig.sol
+
+This contract was compiled with solc ver. 0.66.0
diff --git a/tests/contract/SetcodeMultisig.abi.json b/tests/contract/SetcodeMultisig.abi.json
new file mode 100644
index 0000000..e176f48
--- /dev/null
+++ b/tests/contract/SetcodeMultisig.abi.json
@@ -0,0 +1,155 @@
+{
+ "ABI version": 2,
+ "version": "2.3",
+ "header": ["pubkey", "time", "expire"],
+ "functions": [
+ {
+ "name": "constructor",
+ "inputs": [
+ {"name":"owners","type":"uint256[]"},
+ {"name":"reqConfirms","type":"uint8"},
+ {"name":"lifetime","type":"uint32"}
+ ],
+ "outputs": [
+ ]
+ },
+ {
+ "name": "sendTransaction",
+ "inputs": [
+ {"name":"dest","type":"address"},
+ {"name":"value","type":"uint128"},
+ {"name":"bounce","type":"bool"},
+ {"name":"flags","type":"uint8"},
+ {"name":"payload","type":"cell"}
+ ],
+ "outputs": [
+ ]
+ },
+ {
+ "name": "submitTransaction",
+ "inputs": [
+ {"name":"dest","type":"address"},
+ {"name":"value","type":"uint128"},
+ {"name":"bounce","type":"bool"},
+ {"name":"allBalance","type":"bool"},
+ {"name":"payload","type":"cell"},
+ {"name":"stateInit","type":"optional(cell)"}
+ ],
+ "outputs": [
+ {"name":"transId","type":"uint64"}
+ ]
+ },
+ {
+ "name": "confirmTransaction",
+ "inputs": [
+ {"name":"transactionId","type":"uint64"}
+ ],
+ "outputs": [
+ ]
+ },
+ {
+ "name": "isConfirmed",
+ "inputs": [
+ {"name":"mask","type":"uint32"},
+ {"name":"index","type":"uint8"}
+ ],
+ "outputs": [
+ {"name":"confirmed","type":"bool"}
+ ]
+ },
+ {
+ "name": "getParameters",
+ "inputs": [
+ ],
+ "outputs": [
+ {"name":"maxQueuedTransactions","type":"uint8"},
+ {"name":"maxCustodianCount","type":"uint8"},
+ {"name":"expirationTime","type":"uint64"},
+ {"name":"minValue","type":"uint128"},
+ {"name":"requiredTxnConfirms","type":"uint8"},
+ {"name":"requiredUpdConfirms","type":"uint8"}
+ ]
+ },
+ {
+ "name": "getTransaction",
+ "inputs": [
+ {"name":"transactionId","type":"uint64"}
+ ],
+ "outputs": [
+ {"components":[{"name":"id","type":"uint64"},{"name":"confirmationsMask","type":"uint32"},{"name":"signsRequired","type":"uint8"},{"name":"signsReceived","type":"uint8"},{"name":"creator","type":"uint256"},{"name":"index","type":"uint8"},{"name":"dest","type":"address"},{"name":"value","type":"uint128"},{"name":"sendFlags","type":"uint16"},{"name":"payload","type":"cell"},{"name":"bounce","type":"bool"},{"name":"stateInit","type":"optional(cell)"}],"name":"trans","type":"tuple"}
+ ]
+ },
+ {
+ "name": "getTransactions",
+ "inputs": [
+ ],
+ "outputs": [
+ {"components":[{"name":"id","type":"uint64"},{"name":"confirmationsMask","type":"uint32"},{"name":"signsRequired","type":"uint8"},{"name":"signsReceived","type":"uint8"},{"name":"creator","type":"uint256"},{"name":"index","type":"uint8"},{"name":"dest","type":"address"},{"name":"value","type":"uint128"},{"name":"sendFlags","type":"uint16"},{"name":"payload","type":"cell"},{"name":"bounce","type":"bool"},{"name":"stateInit","type":"optional(cell)"}],"name":"transactions","type":"tuple[]"}
+ ]
+ },
+ {
+ "name": "getCustodians",
+ "inputs": [
+ ],
+ "outputs": [
+ {"components":[{"name":"index","type":"uint8"},{"name":"pubkey","type":"uint256"}],"name":"custodians","type":"tuple[]"}
+ ]
+ },
+ {
+ "name": "submitUpdate",
+ "inputs": [
+ {"name":"codeHash","type":"optional(uint256)"},
+ {"name":"owners","type":"optional(uint256[])"},
+ {"name":"reqConfirms","type":"optional(uint8)"},
+ {"name":"lifetime","type":"optional(uint32)"}
+ ],
+ "outputs": [
+ {"name":"updateId","type":"uint64"}
+ ]
+ },
+ {
+ "name": "confirmUpdate",
+ "inputs": [
+ {"name":"updateId","type":"uint64"}
+ ],
+ "outputs": [
+ ]
+ },
+ {
+ "name": "executeUpdate",
+ "inputs": [
+ {"name":"updateId","type":"uint64"},
+ {"name":"code","type":"optional(cell)"}
+ ],
+ "outputs": [
+ ]
+ },
+ {
+ "name": "getUpdateRequests",
+ "inputs": [
+ ],
+ "outputs": [
+ {"components":[{"name":"id","type":"uint64"},{"name":"index","type":"uint8"},{"name":"signs","type":"uint8"},{"name":"confirmationsMask","type":"uint32"},{"name":"creator","type":"uint256"},{"name":"codeHash","type":"optional(uint256)"},{"name":"custodians","type":"optional(uint256[])"},{"name":"reqConfirms","type":"optional(uint8)"},{"name":"lifetime","type":"optional(uint32)"}],"name":"updates","type":"tuple[]"}
+ ]
+ }
+ ],
+ "data": [
+ ],
+ "events": [
+ ],
+ "fields": [
+ {"name":"_pubkey","type":"uint256"},
+ {"name":"_timestamp","type":"uint64"},
+ {"name":"_constructorFlag","type":"bool"},
+ {"name":"m_ownerKey","type":"uint256"},
+ {"name":"m_requestsMask","type":"uint256"},
+ {"components":[{"name":"id","type":"uint64"},{"name":"confirmationsMask","type":"uint32"},{"name":"signsRequired","type":"uint8"},{"name":"signsReceived","type":"uint8"},{"name":"creator","type":"uint256"},{"name":"index","type":"uint8"},{"name":"dest","type":"address"},{"name":"value","type":"uint128"},{"name":"sendFlags","type":"uint16"},{"name":"payload","type":"cell"},{"name":"bounce","type":"bool"},{"name":"stateInit","type":"optional(cell)"}],"name":"m_transactions","type":"map(uint64,tuple)"},
+ {"name":"m_custodians","type":"map(uint256,uint8)"},
+ {"name":"m_custodianCount","type":"uint8"},
+ {"components":[{"name":"id","type":"uint64"},{"name":"index","type":"uint8"},{"name":"signs","type":"uint8"},{"name":"confirmationsMask","type":"uint32"},{"name":"creator","type":"uint256"},{"name":"codeHash","type":"optional(uint256)"},{"name":"custodians","type":"optional(uint256[])"},{"name":"reqConfirms","type":"optional(uint8)"},{"name":"lifetime","type":"optional(uint32)"}],"name":"m_updateRequests","type":"map(uint64,tuple)"},
+ {"name":"m_updateRequestsMask","type":"uint32"},
+ {"name":"m_requiredVotes","type":"uint8"},
+ {"name":"m_defaultRequiredConfirmations","type":"uint8"},
+ {"name":"m_lifetime","type":"uint32"}
+ ]
+}
diff --git a/tests/contract/SetcodeMultisig.sol b/tests/contract/SetcodeMultisig.sol
new file mode 100644
index 0000000..9387999
--- /dev/null
+++ b/tests/contract/SetcodeMultisig.sol
@@ -0,0 +1,670 @@
+/*
+ Multisignature Wallet with setcode
+ Copyright (C) 2022 Ever Surf
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+pragma ton-solidity >=0.66.0;
+pragma AbiHeader expire;
+pragma AbiHeader pubkey;
+pragma AbiHeader time;
+
+/// @title Multisignature wallet 2.0 with setcode.
+/// @author Ever Surf
+contract MultisigWallet {
+
+ /*
+ * Storage
+ */
+
+ struct Transaction {
+ // Transaction Id.
+ uint64 id;
+ // Transaction confirmations from custodians.
+ uint32 confirmationsMask;
+ // Number of required confirmations.
+ uint8 signsRequired;
+ // Number of confirmations already received.
+ uint8 signsReceived;
+ // Public key of custodian queued transaction.
+ uint256 creator;
+ // Index of custodian.
+ uint8 index;
+ // Recipient address.
+ address dest;
+ // Amount of nanoevers to transfer.
+ uint128 value;
+ // Flags for sending internal message (see SENDRAWMSG in TVM spec).
+ uint16 sendFlags;
+ // Payload used as body of outbound internal message.
+ TvmCell payload;
+ // Bounce flag for header of outbound internal message.
+ bool bounce;
+ // Smart contract image to deploy with internal message.
+ optional(TvmCell) stateInit;
+ }
+
+ /// Request for code update
+ struct UpdateRequest {
+ // request id
+ uint64 id;
+ // index of custodian submitted request
+ uint8 index;
+ // number of confirmations from custodians
+ uint8 signs;
+ // confirmation binary mask
+ uint32 confirmationsMask;
+ // public key of custodian submitted request
+ uint256 creator;
+ // New wallet code hash or null if wallet code should not be changed.
+ optional(uint256) codeHash;
+ // New wallet custodians (pubkeys)
+ optional(uint256[]) custodians;
+ // New number of confirmations required to execute transaction
+ optional(uint8) reqConfirms;
+ // New unconfirmed transaction lifetime in seconds.
+ optional(uint32) lifetime;
+ }
+
+ /*
+ * Constants
+ */
+ uint8 constant MAX_QUEUED_REQUESTS = 5;
+ uint32 constant DEFAULT_LIFETIME = 3600; // lifetime is 1 hour
+ uint32 constant MIN_LIFETIME = 10; // 10 secs
+ uint8 constant MAX_CUSTODIAN_COUNT = 32;
+ uint constant MAX_CLEANUP_TXNS = 40;
+
+ // Send flags.
+ // Forward fees for message will be paid from contract balance.
+ uint8 constant FLAG_PAY_FWD_FEE_FROM_BALANCE = 1;
+ // Ignore errors in action phase to avoid errors if balance is less than sending value.
+ uint8 constant FLAG_IGNORE_ERRORS = 2;
+ // Send all remaining balance.
+ uint8 constant FLAG_SEND_ALL_REMAINING = 128;
+
+ /*
+ * Variables
+ */
+ // Public key of custodian who deployed a contract.
+ uint256 m_ownerKey;
+ // Binary mask with custodian requests (max 32 custodians).
+ uint256 m_requestsMask;
+ // Dictionary of queued transactions waiting for confirmations.
+ mapping(uint64 => Transaction) m_transactions;
+ // Set of custodians, initiated in constructor, but they can be changed later.
+ mapping(uint256 => uint8) m_custodians; // pub_key -> custodian_index
+ // Read-only custodian count, initiated in constructor.
+ uint8 m_custodianCount;
+ // Set of update requests.
+ mapping (uint64 => UpdateRequest) m_updateRequests;
+ // Binary mask for storing update request counts from custodians.
+ // Every custodian can submit only one request.
+ uint32 m_updateRequestsMask;
+ // Minimal number of confirmations required to upgrade wallet code.
+ uint8 m_requiredVotes;
+ // Minimal number of confirmations needed to execute transaction.
+ uint8 m_defaultRequiredConfirmations;
+ // Unconfirmed transaction lifetime, in seconds.
+ uint32 m_lifetime;
+
+ /*
+ Exception codes:
+ 100 - message sender is not a custodian;
+ 102 - transaction does not exist;
+ 103 - operation is already confirmed by this custodian;
+ 107 - input value is too low;
+ 108 - wallet should have only one custodian;
+ 110 - Too many custodians;
+ 113 - Too many requests for one custodian;
+ 115 - update request does not exist;
+ 116 - update request already confirmed by this custodian;
+ 117 - invalid number of custodians;
+ 119 - stored code hash and calculated code hash are not equal;
+ 120 - update request is not confirmed;
+ 121 - payload size is too big;
+ 122 - object is expired;
+ 124 - new custodians are not defined;
+ 125 - `code` argument should be null;
+ 126 - in case of internal deploy: only 1 custodian is allowed;
+ 127 - in case of internal deploy: custodian pubkey must be equal to tvm.pubkey;
+ */
+
+ /*
+ * Constructor
+ */
+
+ /// @dev Internal function called from constructor to initialize custodians.
+ function _initialize(
+ optional(uint256[]) ownersOpt,
+ uint8 reqConfirms,
+ uint32 lifetime
+ ) inline private {
+ if (ownersOpt.hasValue()) {
+ uint8 ownerCount = 0;
+ uint256[] owners = ownersOpt.get();
+ if (owners.length == 0) {
+ owners.push(tvm.pubkey());
+ }
+ m_ownerKey = owners[0];
+ uint256 len = owners.length;
+ delete m_custodians;
+ for (uint256 i = 0; (i < len && ownerCount < MAX_CUSTODIAN_COUNT); i++) {
+ uint256 key = owners[i];
+ if (!m_custodians.exists(key)) {
+ m_custodians[key] = ownerCount++;
+ }
+ }
+ m_custodianCount = ownerCount;
+ }
+
+ m_defaultRequiredConfirmations = math.min(m_custodianCount, reqConfirms);
+
+ m_requiredVotes = (m_custodianCount <= 2) ? m_custodianCount : ((m_custodianCount * 2 + 1) / 3);
+
+ uint32 minLifetime = uint32(m_custodianCount) * MIN_LIFETIME;
+ if (lifetime == 0) {
+ m_lifetime = DEFAULT_LIFETIME;
+ } else {
+ m_lifetime = math.max(minLifetime, math.min(lifetime, uint32(now & 0xFFFFFFFF)));
+ }
+ }
+
+ /// @dev Contract constructor.
+ /// @param owners Array of custodian keys.
+ /// @param reqConfirms Minimal number of confirmations required for executing transaction.
+ /// @param lifetime Unconfirmed transaction lifetime, in seconds.
+ constructor(uint256[] owners, uint8 reqConfirms, uint32 lifetime) public {
+ require(owners.length > 0 && owners.length <= MAX_CUSTODIAN_COUNT, 117);
+ // Allow to deploy from other smart contracts
+ if (msg.sender.value == 0) {
+ // external deploy
+ require(msg.pubkey() == tvm.pubkey(), 100);
+ } else {
+ // internal deploy,
+ // check security condition
+ require(owners.length == 1, 126);
+ require(owners[0] == tvm.pubkey(), 127);
+ }
+ tvm.accept();
+ _initialize(owners, reqConfirms, lifetime);
+ }
+
+ /*
+ * Inline helper macros
+ */
+
+ /// @dev Returns queued transaction count by custodian with defined index.
+ function _getMaskValue(uint256 mask, uint8 index) inline private pure returns (uint8) {
+ return uint8((mask >> (8 * uint256(index))) & 0xFF);
+ }
+
+ /// @dev Increment queued transaction count by custodian with defined index.
+ function _incMaskValue(uint256 mask, uint8 index) inline private pure returns (uint256) {
+ return mask + (1 << (8 * uint256(index)));
+ }
+
+ /// @dev Decrement queued transaction count by custodian with defined index.
+ function _decMaskValue(uint256 mask, uint8 index) inline private pure returns (uint256) {
+ return mask - (1 << (8 * uint256(index)));
+ }
+
+ /// @dev Checks bit with defined index in the mask.
+ function _checkBit(uint32 mask, uint8 index) inline private pure returns (bool) {
+ return (mask & (uint32(1) << index)) != 0;
+ }
+
+ /// @dev Checks if object is confirmed by custodian.
+ function _isConfirmed(uint32 mask, uint8 custodianIndex) inline private pure returns (bool) {
+ return _checkBit(mask, custodianIndex);
+ }
+
+ function _isSubmitted(uint32 mask, uint8 custodianIndex) inline private pure returns (bool) {
+ return _checkBit(mask, custodianIndex);
+ }
+
+ /// @dev Sets custodian confirmation bit in the mask.
+ function _setConfirmed(uint32 mask, uint8 custodianIndex) inline private pure returns (uint32) {
+ mask |= (uint32(1) << custodianIndex);
+ return mask;
+ }
+
+ /// @dev Checks that custodian with supplied public key exists in custodian set.
+ function _findCustodian(uint256 senderKey) inline private view returns (uint8) {
+ optional(uint8) custodianIndex = m_custodians.fetch(senderKey);
+ require(custodianIndex.hasValue(), 100);
+ return custodianIndex.get();
+ }
+
+ /// @dev Generates new id for transaction.
+ function _generateId() inline private pure returns (uint64) {
+ return (uint64(now) << 32) | (tx.timestamp & 0xFFFFFFFF);
+ }
+
+ /// @dev Returns timestamp after which transactions are treated as expired.
+ function _getExpirationBound() inline private view returns (uint64) {
+ return (uint64(now) - uint64(m_lifetime)) << 32;
+ }
+
+ /// @dev Returns transfer flags according to input value and `allBalance` flag.
+ function _getSendFlags(uint128 value, bool allBalance) inline private pure returns (uint8, uint128) {
+ uint8 flags = FLAG_IGNORE_ERRORS | FLAG_PAY_FWD_FEE_FROM_BALANCE;
+ if (allBalance) {
+ flags = FLAG_IGNORE_ERRORS | FLAG_SEND_ALL_REMAINING;
+ value = 0;
+ }
+ return (flags, value);
+ }
+
+ /*
+ * Public functions
+ */
+
+ /// @dev Allows custodian if she is the only owner of multisig to transfer funds with minimal fees.
+ /// @param dest Transfer target address.
+ /// @param value Amount of funds to transfer.
+ /// @param bounce Bounce flag. Set true to transfer funds to existing account,
+ /// set false to create new account.
+ /// @param flags `sendmsg` flags.
+ /// @param payload Tree of cells used as body of outbound internal message.
+ function sendTransaction(
+ address dest,
+ uint128 value,
+ bool bounce,
+ uint8 flags,
+ TvmCell payload
+ ) public view {
+ require(m_custodianCount == 1, 108);
+ require(msg.pubkey() == m_ownerKey, 100);
+ tvm.accept();
+ dest.transfer(value, bounce, flags | FLAG_IGNORE_ERRORS, payload);
+ }
+
+ /// @dev Allows custodians to submit new transaction.
+ /// @param dest Transfer target address.
+ /// @param value Nanoevers value to transfer.
+ /// @param bounce Bounce flag. Set true if need to transfer evers to existing account; set false to create new account.
+ /// @param allBalance Set true if need to transfer all remaining balance.
+ /// @param payload Tree of cells used as body of outbound internal message.
+ /// @param stateInit Smart contract image to deploy with internal message.
+ /// @return transId Transaction ID.
+ function submitTransaction(
+ address dest,
+ uint128 value,
+ bool bounce,
+ bool allBalance,
+ TvmCell payload,
+ optional(TvmCell) stateInit
+ ) public returns (uint64 transId) {
+ uint256 senderKey = msg.pubkey();
+ uint8 index = _findCustodian(senderKey);
+ _removeExpiredTransactions();
+ require(_getMaskValue(m_requestsMask, index) < MAX_QUEUED_REQUESTS, 113);
+ tvm.accept();
+
+ (uint8 flags, uint128 realValue) = _getSendFlags(value, allBalance);
+
+ m_requestsMask = _incMaskValue(m_requestsMask, index);
+ uint64 trId = _generateId();
+ Transaction txn = Transaction({
+ id: trId,
+ confirmationsMask: 0,
+ signsRequired: m_defaultRequiredConfirmations,
+ signsReceived: 0,
+ creator: senderKey,
+ index: index,
+ dest: dest,
+ value: realValue,
+ sendFlags: flags,
+ payload: payload,
+ bounce: bounce,
+ stateInit: stateInit
+ });
+
+ _confirmTransaction(txn, index);
+ return trId;
+ }
+
+ /// @dev Allows custodian to confirm a transaction.
+ /// @param transactionId Transaction ID.
+ function confirmTransaction(uint64 transactionId) public {
+ uint8 index = _findCustodian(msg.pubkey());
+ _removeExpiredTransactions();
+ optional(Transaction) txnOpt = m_transactions.fetch(transactionId);
+ require(txnOpt.hasValue(), 102);
+ Transaction txn = txnOpt.get();
+ require(!_isConfirmed(txn.confirmationsMask, index), 103);
+ tvm.accept();
+ _confirmTransaction(txn, index);
+ }
+
+ /*
+ * Internal functions
+ */
+
+ /// @dev Confirms transaction by custodian with defined index.
+ /// @param txn Transaction object to confirm.
+ /// @param custodianIndex Ccustodian index which confirms transaction.
+ function _confirmTransaction(
+ Transaction txn,
+ uint8 custodianIndex
+ ) inline private {
+ if ((txn.signsReceived + 1) >= txn.signsRequired) {
+ if (txn.stateInit.hasValue()) {
+ txn.dest.transfer({
+ value: txn.value,
+ bounce: txn.bounce,
+ flag: txn.sendFlags,
+ body: txn.payload,
+ stateInit: txn.stateInit.get()
+ });
+ } else {
+ txn.dest.transfer({
+ value: txn.value,
+ bounce: txn.bounce,
+ flag: txn.sendFlags,
+ body: txn.payload
+ });
+ }
+ m_requestsMask = _decMaskValue(m_requestsMask, txn.index);
+ delete m_transactions[txn.id];
+ } else {
+ txn.confirmationsMask = _setConfirmed(txn.confirmationsMask, custodianIndex);
+ txn.signsReceived++;
+ m_transactions[txn.id] = txn;
+ }
+ }
+
+ /// @dev Removes expired transactions from storage.
+ function _removeExpiredTransactions() private {
+ uint64 marker = _getExpirationBound();
+ if (m_transactions.empty()) return;
+
+ (uint64 trId, Transaction txn) = m_transactions.min().get();
+ bool needCleanup = trId <= marker;
+
+ if (needCleanup) {
+ tvm.accept();
+ uint i = 0;
+ while (needCleanup && i < MAX_CLEANUP_TXNS) {
+ i++;
+ // transaction is expired, remove it
+ m_requestsMask = _decMaskValue(m_requestsMask, txn.index);
+ delete m_transactions[trId];
+ optional(uint64, Transaction) nextTxn = m_transactions.next(trId);
+ if (nextTxn.hasValue()) {
+ (trId, txn) = nextTxn.get();
+ needCleanup = trId <= marker;
+ } else {
+ needCleanup = false;
+ }
+ }
+ tvm.commit();
+ }
+ }
+
+ /*
+ * Get methods
+ */
+
+ /// @dev Helper get-method for checking if custodian confirmation bit is set.
+ /// @return confirmed True if confirmation bit is set.
+ function isConfirmed(uint32 mask, uint8 index) external pure returns (bool confirmed) {
+ confirmed = _isConfirmed(mask, index);
+ }
+
+ /// @dev Get-method that returns wallet configuration parameters.
+ /// @return maxQueuedTransactions The maximum number of unconfirmed transactions that a custodian can submit.
+ /// @return maxCustodianCount The maximum allowed number of wallet custodians.
+ /// @return expirationTime Transaction lifetime in seconds.
+ /// @return minValue The minimum value allowed to transfer in one transaction.
+ /// @return requiredTxnConfirms The minimum number of confirmations required to execute transaction.
+ /// @return requiredUpdConfirms The minimum number of confirmations required to update wallet code.
+ function getParameters() external view
+ returns (uint8 maxQueuedTransactions,
+ uint8 maxCustodianCount,
+ uint64 expirationTime,
+ uint128 minValue,
+ uint8 requiredTxnConfirms,
+ uint8 requiredUpdConfirms) {
+
+ maxQueuedTransactions = MAX_QUEUED_REQUESTS;
+ maxCustodianCount = MAX_CUSTODIAN_COUNT;
+ expirationTime = m_lifetime;
+ minValue = 0;
+ requiredTxnConfirms = m_defaultRequiredConfirmations;
+ requiredUpdConfirms = m_requiredVotes;
+ }
+
+ /// @dev Get-method that returns transaction info by id.
+ /// @return trans Transaction structure.
+ /// Throws exception if transaction does not exist.
+ function getTransaction(uint64 transactionId) external view
+ returns (Transaction trans) {
+ optional(Transaction) txnOpt = m_transactions.fetch(transactionId);
+ require(txnOpt.hasValue(), 102);
+ trans = txnOpt.get();
+ }
+
+ /// @dev Get-method that returns array of pending transactions.
+ /// Returns not expired transactions only.
+ /// @return transactions Array of queued transactions.
+ function getTransactions() external view returns (Transaction[] transactions) {
+ uint64 bound = _getExpirationBound();
+ for ((uint64 id, Transaction txn): m_transactions) {
+ // returns only not expired transactions
+ if (id > bound) {
+ transactions.push(txn);
+ }
+ }
+ }
+
+ /// @dev Helper structure to return information about custodian.
+ /// Used in getCustodians().
+ struct CustodianInfo {
+ uint8 index;
+ uint256 pubkey;
+ }
+
+ /// @dev Get-method that returns info about wallet custodians.
+ /// @return custodians Array of custodians.
+ function getCustodians() external view returns (CustodianInfo[] custodians) {
+ for ((uint256 key, uint8 index): m_custodians) {
+ custodians.push(CustodianInfo(index, key));
+ }
+ }
+
+ /*
+ SETCODE public functions
+ */
+
+ /// @dev Allows to submit update request. New custodians can be supplied.
+ /// @param codeHash New wallet code hash.
+ /// @param owners New wallet custodians (array of pubkeys).
+ /// @param reqConfirms New number of confirmations required for executing transaction.
+ /// @param lifetime New unconfirmed transaction lifetime, in seconds.
+ /// @return updateId Id of submitted update request.
+ function submitUpdate(
+ optional(uint256) codeHash,
+ optional(uint256[]) owners,
+ optional(uint8) reqConfirms,
+ optional(uint32) lifetime
+ ) public returns (uint64 updateId) {
+ uint256 sender = msg.pubkey();
+ uint8 index = _findCustodian(sender);
+ if (owners.hasValue()) {
+ uint newOwnerCount = owners.get().length;
+ require(newOwnerCount > 0 && newOwnerCount <= MAX_CUSTODIAN_COUNT, 117);
+ }
+ _removeExpiredUpdateRequests();
+ require(!_isSubmitted(m_updateRequestsMask, index), 113);
+ tvm.accept();
+
+ if (codeHash.hasValue()) {
+ if (codeHash.get() == tvm.hash(tvm.code())) {
+ codeHash.reset();
+ }
+ }
+ m_updateRequestsMask = _setConfirmed(m_updateRequestsMask, index);
+ updateId = _generateId();
+ m_updateRequests[updateId] = UpdateRequest({
+ id: updateId,
+ index: index,
+ signs: 0,
+ confirmationsMask: 0,
+ creator: sender,
+ codeHash: codeHash,
+ custodians: owners,
+ reqConfirms: reqConfirms,
+ lifetime: lifetime
+ });
+ _confirmUpdate(updateId, index);
+ }
+
+ /// @dev Allow to confirm submitted update request. Call executeUpdate to do `setcode`
+ /// after necessary confirmation count.
+ /// @param updateId Id of submitted update request.
+ function confirmUpdate(uint64 updateId) public {
+ uint8 index = _findCustodian(msg.pubkey());
+ _removeExpiredUpdateRequests();
+ optional(UpdateRequest) requestOpt = m_updateRequests.fetch(updateId);
+ require(requestOpt.hasValue(), 115);
+ require(!_isConfirmed(requestOpt.get().confirmationsMask, index), 116);
+ tvm.accept();
+
+ _confirmUpdate(updateId, index);
+ }
+
+ /// @dev Allows to execute confirmed update request.
+ /// @param updateId Id of update request.
+ /// @param code Root cell of tree of cells with contract code.
+ function executeUpdate(uint64 updateId, optional(TvmCell) code) public {
+ require(m_custodians.exists(msg.pubkey()), 100);
+ _removeExpiredUpdateRequests();
+ optional(UpdateRequest) requestOpt = m_updateRequests.fetch(updateId);
+ require(requestOpt.hasValue(), 115);
+ UpdateRequest request = requestOpt.get();
+ if (request.codeHash.hasValue()) {
+ require(code.hasValue(), 119);
+ require(tvm.hash(code.get()) == request.codeHash.get(), 119);
+ } else {
+ require(!code.hasValue(), 125);
+ }
+ require(request.signs >= m_requiredVotes, 120);
+
+ tvm.accept();
+
+ _deleteUpdateRequest(updateId, request.index);
+
+ tvm.commit();
+ if (request.codeHash.hasValue()) {
+ TvmCell newcode = code.get();
+ tvm.setcode(newcode);
+ tvm.setCurrentCode(newcode);
+ }
+
+ TvmBuilder data;
+ if (request.custodians.hasValue()) {
+ data.store(true, request.custodians.get());
+ } else {
+ data.store(false, m_custodians, m_custodianCount, m_ownerKey);
+ }
+ if (request.reqConfirms.hasValue()) {
+ data.store(request.reqConfirms.get());
+ } else {
+ data.store(m_defaultRequiredConfirmations);
+ }
+ if (request.lifetime.hasValue()) {
+ data.store(request.lifetime.get());
+ } else {
+ data.store(m_lifetime);
+ }
+ onCodeUpgrade(data.toCell());
+ }
+
+ /// @dev Get-method to query all pending update requests.
+ function getUpdateRequests() external view returns (UpdateRequest[] updates) {
+ uint64 bound = _getExpirationBound();
+ for ((uint64 updateId, UpdateRequest req): m_updateRequests) {
+ if (updateId > bound) {
+ updates.push(req);
+ }
+ }
+ }
+
+ /// @dev Old handler after code update. For compatibility with old msig.
+ function onCodeUpgrade(uint256[] newOwners, uint8 reqConfirms) private functionID(2) {
+ tvm.resetStorage();
+ _initialize(newOwners, reqConfirms, 0);
+ }
+
+ /// @dev Handler after code update.
+ function onCodeUpgrade(TvmCell data) private functionID(3) {
+ tvm.resetStorage();
+ optional(uint256[]) owners;
+ TvmSlice slice = data.toSlice();
+ bool ownersAsArray = slice.decode(bool);
+ if (ownersAsArray) {
+ owners = slice.decode(uint256[]);
+ } else {
+ (m_custodians, m_custodianCount, m_ownerKey) = slice.decode(
+ mapping(uint256 => uint8), uint8, uint256);
+ }
+
+ (uint8 reqConfirms, uint32 lifetime) = slice.decode(uint8, uint32);
+ _initialize(owners, reqConfirms, lifetime);
+ }
+
+ /*
+ * Internal functions
+ */
+
+ /// @dev Internal function for update confirmation.
+ function _confirmUpdate(uint64 updateId, uint8 custodianIndex) inline private {
+ UpdateRequest request = m_updateRequests[updateId];
+ request.signs++;
+ request.confirmationsMask = _setConfirmed(request.confirmationsMask, custodianIndex);
+ m_updateRequests[updateId] = request;
+ }
+
+ /// @dev Removes expired update requests.
+ function _removeExpiredUpdateRequests() inline private {
+ uint64 marker = _getExpirationBound();
+ if (m_updateRequests.empty()) return;
+
+ (uint64 updateId, UpdateRequest req) = m_updateRequests.min().get();
+ bool needCleanup = updateId <= marker;
+ if (needCleanup) {
+ tvm.accept();
+ while (needCleanup) {
+ // request is expired, remove it
+ _deleteUpdateRequest(updateId, req.index);
+ optional(uint64, UpdateRequest) reqOpt = m_updateRequests.next(updateId);
+ if (reqOpt.hasValue()) {
+ (updateId, req) = reqOpt.get();
+ needCleanup = updateId <= marker;
+ } else {
+ needCleanup = false;
+ }
+ }
+ tvm.commit();
+ }
+ }
+
+ /// @dev Helper function to correctly delete request.
+ function _deleteUpdateRequest(uint64 updateId, uint8 index) inline private {
+ m_updateRequestsMask &= ~(uint32(1) << index);
+ delete m_updateRequests[updateId];
+ }
+}
diff --git a/tests/contract/SetcodeMultisig.tvc b/tests/contract/SetcodeMultisig.tvc
new file mode 100644
index 0000000..2419b75
Binary files /dev/null and b/tests/contract/SetcodeMultisig.tvc differ
diff --git a/tests/package-lock.json b/tests/package-lock.json
new file mode 100644
index 0000000..79c2950
--- /dev/null
+++ b/tests/package-lock.json
@@ -0,0 +1,3484 @@
+{
+ "name": "msig-wallet",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "@eversdk/core": "^1.41.1",
+ "@eversdk/lib-node": "^1.41.1",
+ "ts-node": "^10.9.1"
+ },
+ "devDependencies": {
+ "@types/node": "^16.0.1",
+ "@typescript-eslint/eslint-plugin": "^5.57.1",
+ "@typescript-eslint/parser": "^5.57.1",
+ "eslint": "^7.30.0",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-plugin-prettier": "^4.0.0",
+ "prettier": "^2.3.2",
+ "typescript": "^4.6.3"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+ "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "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/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
+ "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
+ "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.1.1",
+ "espree": "^7.3.0",
+ "globals": "^13.9.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@eversdk/core": {
+ "version": "1.42.1",
+ "resolved": "https://registry.npmjs.org/@eversdk/core/-/core-1.42.1.tgz",
+ "integrity": "sha512-Wm93n/t6rBhGmbkV7OEsB+/DAD5OfCNOyhNARPWqBmjNLiamHLhzsO8LC293WM2Z4UxT9N0Gp4PsL2V6mrliaA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@eversdk/lib-node": {
+ "version": "1.42.1",
+ "resolved": "https://registry.npmjs.org/@eversdk/lib-node/-/lib-node-1.42.1.tgz",
+ "integrity": "sha512-STLOP500pwGOrxeL/zkBG7Zscwc4BkTdDVqJ7pswPcfrWq5FBuk9H2nolXjQ85RZHF9eisGH9WBVSddHmzR1eg==",
+ "hasInstallScript": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
+ "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.0",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
+ "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
+ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "16.18.25",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.25.tgz",
+ "integrity": "sha512-rUDO6s9Q/El1R1I21HG4qw/LstTHCPO/oQNAwI/4b2f9EWvMnqt4d3HJwPMawfZ3UvodB8516Yg+VAq54YM+eA=="
+ },
+ "node_modules/@types/semver": {
+ "version": "7.3.13",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+ "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz",
+ "integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.4.0",
+ "@typescript-eslint/scope-manager": "5.59.2",
+ "@typescript-eslint/type-utils": "5.59.2",
+ "@typescript-eslint/utils": "5.59.2",
+ "debug": "^4.3.4",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz",
+ "integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.59.2",
+ "@typescript-eslint/types": "5.59.2",
+ "@typescript-eslint/typescript-estree": "5.59.2",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz",
+ "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.59.2",
+ "@typescript-eslint/visitor-keys": "5.59.2"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz",
+ "integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "5.59.2",
+ "@typescript-eslint/utils": "5.59.2",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz",
+ "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz",
+ "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.59.2",
+ "@typescript-eslint/visitor-keys": "5.59.2",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz",
+ "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.59.2",
+ "@typescript-eslint/types": "5.59.2",
+ "@typescript-eslint/typescript-estree": "5.59.2",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz",
+ "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.59.2",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/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/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/create-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "7.32.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz",
+ "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "7.12.11",
+ "@eslint/eslintrc": "^0.4.3",
+ "@humanwhocodes/config-array": "^0.5.0",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "enquirer": "^2.3.5",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^2.1.0",
+ "eslint-visitor-keys": "^2.0.0",
+ "espree": "^7.3.1",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.1.2",
+ "globals": "^13.6.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.0.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "progress": "^2.0.0",
+ "regexpp": "^3.1.0",
+ "semver": "^7.2.1",
+ "strip-ansi": "^6.0.0",
+ "strip-json-comments": "^3.1.0",
+ "table": "^6.0.9",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz",
+ "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
+ "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.28.0",
+ "prettier": ">=2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
+ "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint/node_modules/ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/espree": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^7.4.0",
+ "acorn-jsx": "^5.3.1",
+ "eslint-visitor-keys": "^1.3.0"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "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/globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "node_modules/has-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/ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-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-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/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
+ "dev": true
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/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/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve-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/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz",
+ "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/table": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
+ "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/table/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "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/table/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==",
+ "dev": true
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-node": {
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
+ "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-node/node_modules/acorn": {
+ "version": "8.8.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-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/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
+ },
+ "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/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/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/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ }
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+ "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "requires": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ }
+ },
+ "@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "@eslint-community/regexpp": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
+ "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
+ "dev": true
+ },
+ "@eslint/eslintrc": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
+ "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.1.1",
+ "espree": "^7.3.0",
+ "globals": "^13.9.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "strip-json-comments": "^3.1.1"
+ },
+ "dependencies": {
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ }
+ }
+ },
+ "@eversdk/core": {
+ "version": "1.42.1",
+ "resolved": "https://registry.npmjs.org/@eversdk/core/-/core-1.42.1.tgz",
+ "integrity": "sha512-Wm93n/t6rBhGmbkV7OEsB+/DAD5OfCNOyhNARPWqBmjNLiamHLhzsO8LC293WM2Z4UxT9N0Gp4PsL2V6mrliaA=="
+ },
+ "@eversdk/lib-node": {
+ "version": "1.42.1",
+ "resolved": "https://registry.npmjs.org/@eversdk/lib-node/-/lib-node-1.42.1.tgz",
+ "integrity": "sha512-STLOP500pwGOrxeL/zkBG7Zscwc4BkTdDVqJ7pswPcfrWq5FBuk9H2nolXjQ85RZHF9eisGH9WBVSddHmzR1eg=="
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
+ "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.0",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA=="
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@tsconfig/node10": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
+ "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
+ },
+ "@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
+ },
+ "@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
+ },
+ "@tsconfig/node16": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
+ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
+ },
+ "@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "16.18.25",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.25.tgz",
+ "integrity": "sha512-rUDO6s9Q/El1R1I21HG4qw/LstTHCPO/oQNAwI/4b2f9EWvMnqt4d3HJwPMawfZ3UvodB8516Yg+VAq54YM+eA=="
+ },
+ "@types/semver": {
+ "version": "7.3.13",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+ "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
+ "dev": true
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz",
+ "integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/regexpp": "^4.4.0",
+ "@typescript-eslint/scope-manager": "5.59.2",
+ "@typescript-eslint/type-utils": "5.59.2",
+ "@typescript-eslint/utils": "5.59.2",
+ "debug": "^4.3.4",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz",
+ "integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "5.59.2",
+ "@typescript-eslint/types": "5.59.2",
+ "@typescript-eslint/typescript-estree": "5.59.2",
+ "debug": "^4.3.4"
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz",
+ "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.59.2",
+ "@typescript-eslint/visitor-keys": "5.59.2"
+ }
+ },
+ "@typescript-eslint/type-utils": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz",
+ "integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/typescript-estree": "5.59.2",
+ "@typescript-eslint/utils": "5.59.2",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz",
+ "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz",
+ "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.59.2",
+ "@typescript-eslint/visitor-keys": "5.59.2",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/utils": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz",
+ "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.59.2",
+ "@typescript-eslint/types": "5.59.2",
+ "@typescript-eslint/typescript-estree": "5.59.2",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "5.59.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz",
+ "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.59.2",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "acorn-walk": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "create-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "eslint": {
+ "version": "7.32.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz",
+ "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "7.12.11",
+ "@eslint/eslintrc": "^0.4.3",
+ "@humanwhocodes/config-array": "^0.5.0",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "enquirer": "^2.3.5",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^2.1.0",
+ "eslint-visitor-keys": "^2.0.0",
+ "espree": "^7.3.1",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.1.2",
+ "globals": "^13.6.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.0.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "progress": "^2.0.0",
+ "regexpp": "^3.1.0",
+ "semver": "^7.2.1",
+ "strip-ansi": "^6.0.0",
+ "strip-json-comments": "^3.1.0",
+ "table": "^6.0.9",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-config-prettier": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz",
+ "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-plugin-prettier": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
+ "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
+ "dev": true,
+ "requires": {
+ "prettier-linter-helpers": "^1.0.0"
+ }
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
+ "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
+ "dev": true
+ },
+ "espree": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.4.0",
+ "acorn-jsx": "^5.3.1",
+ "eslint-visitor-keys": "^1.3.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-diff": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "has-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
+ },
+ "ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true
+ },
+ "prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "requires": {
+ "fast-diff": "^1.1.2"
+ }
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true
+ },
+ "punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true
+ },
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true
+ },
+ "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
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "semver": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz",
+ "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "table": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
+ "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "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==",
+ "dev": true
+ }
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "ts-node": {
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
+ "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
+ "requires": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "8.8.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-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
+ },
+ "typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
+ }
+ }
+}
diff --git a/tests/package.json b/tests/package.json
new file mode 100644
index 0000000..3eca2b5
--- /dev/null
+++ b/tests/package.json
@@ -0,0 +1,10 @@
+{
+ "scripts": {
+ "msig-wallet": "npx ts-node src/wallet.ts"
+ },
+ "dependencies": {
+ "@eversdk/core": "^1.41.1",
+ "@eversdk/lib-node": "^1.41.1",
+ "ts-node": "^10.9.1"
+ }
+}
diff --git a/tests/src/listTransactions.ts b/tests/src/listTransactions.ts
new file mode 100644
index 0000000..5b1f13c
--- /dev/null
+++ b/tests/src/listTransactions.ts
@@ -0,0 +1,77 @@
+import { libNode } from '@eversdk/lib-node'
+import { TonClient, ResultOfQuery } from '@eversdk/core'
+import assert from 'node:assert/strict';
+
+TonClient.useBinaryLibrary(libNode)
+
+const endpoint = process.env.ENDPOINT
+assert.ok(endpoint,
+ "An endpoint is required. You can find it when creating a project at https://dashboard.evercloud.dev"
+)
+const client = new TonClient({ network: { endpoints: [endpoint] } })
+
+async function main(client: TonClient) {
+ // In this example, we want the query to return 2 items per page.
+ const itemsPerPage = 25
+
+ // Pagination connection pattern requires a cursor, which will be set latter
+ let cursor: string = undefined
+
+ // The idiomatic way to send a request is to specify
+ // query and variables as separate properties.
+ const transactionsQuery = `
+ query listTransactions($cursor: String, $count: Int) {
+ blockchain {
+ transactions(
+ workchain: 0
+ first: $count
+ after: $cursor
+ ) {
+ edges {
+ node { id }
+ }
+ pageInfo { hasNextPage endCursor }
+ }
+ }
+ }`
+
+ for (; ;) {
+ const queryResult: ResultOfQuery = await client.net.query({
+ query: transactionsQuery,
+ variables: {
+ count: itemsPerPage,
+ cursor
+ }
+ });
+ const transactions = queryResult.result.data.blockchain.transactions;
+
+ for (const edge of transactions.edges) {
+ console.log("Transaction id:", edge.node.id);
+ }
+ if (transactions.pageInfo.hasNextPage === false) {
+ break;
+ }
+ // To read next page we initialize the cursor:
+ cursor = transactions.pageInfo.endCursor;
+ // TODO: rate limiting
+ await sleep(1000);
+ }
+
+}
+console.log("Getting all transactions in workchain 0 from the beginning/")
+console.log("Most likely this process will never end, so press CTRL+C to interrupt it")
+main(client)
+ .then(() => {
+ process.exit(0)
+ })
+ .catch(error => {
+ console.error(error);
+ process.exit(1);
+ })
+
+
+
+// This helper function is used for limiting request rate
+function sleep(ms: number) { return new Promise(r => setTimeout(r, ms)) }
+
+
diff --git a/tests/src/subscription.ts b/tests/src/subscription.ts
new file mode 100644
index 0000000..ad9aec8
--- /dev/null
+++ b/tests/src/subscription.ts
@@ -0,0 +1,75 @@
+import { libNode } from '@eversdk/lib-node'
+import { TonClient } from '@eversdk/core'
+import assert from 'node:assert/strict';
+
+TonClient.useBinaryLibrary(libNode)
+
+const endpoint = process.env.ENDPOINT
+assert.ok(endpoint,
+ "An endpoint is required. You can find it when creating a project at https://dashboard.evercloud.dev"
+)
+// List of account to subscribe
+const addressList = [
+ "-1:3333333333333333333333333333333333333333333333333333333333333333",
+ "0:40e593373fd9c972162812878ea1976ebaffe2bff030c637df2c08826cf1583b"
+]
+
+async function main() {
+ try {
+ const client = new TonClient({ network: { endpoints: [endpoint] } })
+
+ const queryText = `
+ subscription my($list: [String!]!){
+ transactions(
+ filter: {account_addr: { in: $list }}
+ ) {
+ id
+ account_addr
+ balance_delta
+ }
+ }`
+
+ // use `client.net.unsubscribe({ handle })` to close subscription
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const { handle } = await client.net.subscribe(
+ {
+ subscription: queryText,
+ variables: { list: addressList }
+ },
+ responseHandler,
+ );
+ console.log("Subscribed to transactions of accounts:", JSON.stringify(addressList))
+ console.log("Press CTRL+C to interrupt it")
+
+ } catch (error) {
+ if (error.code === 504) {
+ console.error('Network is inaccessible.');
+ } else {
+ console.error(error);
+ }
+ process.exit(1);
+ }
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function responseHandler(params: any, responseType: number) {
+ // Tip: Always wrap the logic inside responseHandler in a try-catch block
+ // or you will be surprised by non-informative errors due to the context
+ // in which the handler is executed
+ try {
+ if (responseType === 100 /* GraphQL data received */) {
+ if (params?.result) {
+ console.log(params.result);
+ }
+
+ } else {
+ // See full list of error codes here:
+ // https://docs.everos.dev/ever-sdk/reference/types-and-methods/mod_net#neterrorcode
+ console.error(params, responseType);
+ }
+ } catch (err) {
+ console.log(err);
+ }
+}
+
+main()
diff --git a/tests/src/wallet.ts b/tests/src/wallet.ts
new file mode 100644
index 0000000..736db6b
--- /dev/null
+++ b/tests/src/wallet.ts
@@ -0,0 +1,208 @@
+import { libNode } from '@eversdk/lib-node'
+import { readFileSync } from 'node:fs'
+import path from 'node:path'
+import { TonClient, ResultOfQuery, ParamsOfEncodeMessage, ResultOfEncodeMessage, ResultOfProcessMessage } from '@eversdk/core'
+import assert from 'node:assert/strict';
+
+TonClient.useBinaryLibrary(libNode)
+
+const endpoint = process.env.ENDPOINT
+assert.ok(endpoint,
+ "An endpoint is required. You can find it when creating a project at https://dashboard.evercloud.dev"
+)
+const client = new TonClient({ network: { endpoints: [endpoint] } })
+
+// To run this test, you need to send at least this amount in tokens to the specified account
+const MINIMAL_BALANCE = 1
+
+async function main(client: TonClient) {
+ //
+ // 1. ------------------ Deploy multisig wallet --------------------------------
+ //
+ // Generate a key pair for the wallet to be deployed
+ const keypair = await client.crypto.generate_random_sign_keys();
+
+ // To deploy a wallet we need its TVC and ABI files
+ const msigTVC: string =
+ readFileSync(path.resolve(__dirname, "../contract/SetcodeMultisig.tvc")).toString("base64")
+ const msigABI: string =
+ readFileSync(path.resolve(__dirname, "../contract/SetcodeMultisig.abi.json")).toString("utf8")
+
+ // We need to know the future address of the wallet account,
+ // because its balance must be positive for the contract to be deployed
+ // Future address can be calculated by encoding the deploy message.
+ // https://docs.everos.dev/ever-sdk/reference/types-and-methods/mod_abi#encode_message
+
+ const messageParams: ParamsOfEncodeMessage = {
+ abi: { type: 'Json', value: msigABI },
+ deploy_set: { tvc: msigTVC, initial_data: {} },
+ signer: { type: 'Keys', keys: keypair },
+ processing_try_index: 1
+ }
+
+ const encoded: ResultOfEncodeMessage = await client.abi.encode_message(messageParams)
+
+ const msigAddress = encoded.address
+
+ console.log(`You can topup your wallet from dashboard at https://dashboard.evercloud.dev`)
+ console.log(`Please send >= ${MINIMAL_BALANCE} tokens to ${msigAddress}`)
+ console.log(`awaiting...`)
+
+ // Blocking here, waiting for account balance changes.
+ // It is assumed that at this time you go to dashboard.evercloud.dev
+ // and replenish this account.
+ let balance: number
+ let accType: number
+ for (; ;) {
+ // The idiomatic way to send a request is to specify
+ // query and variables as separate properties.
+ const getInfoQuery = `
+ query getBalance($address: String!) {
+ blockchain {
+ account(address: $address) {
+ info {
+ balance
+ acc_type
+ }
+ }
+ }
+ }
+ `
+ const resultOfQuery: ResultOfQuery = await client.net.query({
+ query: getInfoQuery,
+ variables: { address: msigAddress }
+ })
+
+ const nanotokens = parseInt(resultOfQuery.result.data.blockchain.account.info?.balance, 16)
+ accType = resultOfQuery.result.data.blockchain.account.info?.acc_type;
+ if (nanotokens > MINIMAL_BALANCE * 1e9) {
+ balance = nanotokens / 1e9
+ break
+ }
+ // TODO: rate limiting
+ await sleep(1000)
+ }
+ console.log(`Account balance is: ${balance.toString(10)} tokens. Account type is ${accType}`)
+
+ console.log(`Deploying wallet contract to address: ${msigAddress} and waiting for transaction...`)
+
+ // This function returns type `ResultOfProcessMessage`, see:
+ // https://docs.everos.dev/ever-sdk/reference/types-and-methods/mod_processing#process_message
+ let result: ResultOfProcessMessage = await client.processing.process_message({
+ message_encode_params: {
+ ...messageParams, // use the same params as for `encode_message`,
+ call_set: { // plus add `call_set`
+ function_name: 'constructor',
+ input: {
+ owners: [`0x${keypair.public}`],
+ reqConfirms: 0,
+ lifetime: 0
+ }
+ },
+ },
+ send_events: false,
+ })
+ console.log('Contract deployed. Transaction hash', result.transaction?.id)
+ assert.equal(result.transaction?.status, 3)
+ assert.equal(result.transaction?.status_name, "finalized")
+
+ //
+ // 2.----------------------- Transfer tokens ------------------------
+ //
+ // We send 0.5 tokens. Value is written in nanotokens
+ const amount = 0.5e9
+ const dest = "-1:7777777777777777777777777777777777777777777777777777777777777777"
+
+ console.log('Sending 0.5 token to', dest)
+
+ result = await client.processing.process_message({
+ message_encode_params: {
+ address: msigAddress,
+ ...messageParams, // use the same params as for `encode_message`,
+ call_set: { // plus add `call_set`
+ function_name: 'sendTransaction',
+ input: {
+ dest: dest,
+ value: amount,
+ bounce: false,
+ flags: 64,
+ payload: ''
+ }
+ },
+ },
+ send_events: false, // do not send intermidate events
+ })
+ console.log('Transfer completed. Transaction hash', result.transaction?.id)
+ assert.equal(result.transaction?.status, 3)
+ assert.equal(result.transaction?.status_name, "finalized")
+
+ //
+ // 3.----------------- Read all wallet transactions -----------------------
+ //
+ const accountQuery = `
+ query getTransactions($address: String!, $cursor: String, $count: Int) {
+ blockchain {
+ account(address: $address) {
+ transactions(
+ first: $count,
+ after: $cursor,
+ allow_latest_inconsistent_data: true
+ ) {
+ edges {
+ node { hash }
+ }
+ pageInfo {
+ endCursor
+ hasNextPage
+ }
+ }
+ }
+ }
+ }`
+
+ // Pagination connection pattern requires a cursor, that will be set latter
+ let cursor: string = undefined
+
+ // In this example, we want the query to return 2 items per page.
+ const itemsPerPage = 2
+
+ for (; ;) {
+ const queryResult: ResultOfQuery = await client.net.query({
+ query: accountQuery,
+ variables: {
+ address: msigAddress,
+ count: itemsPerPage,
+ cursor
+ }
+ });
+ const transactions = queryResult.result.data.blockchain.account.transactions;
+
+ for (const edge of transactions.edges) {
+ console.log("Transaction hash:", edge.node.hash);
+ }
+ if (transactions.pageInfo.hasNextPage === false) {
+ break;
+ }
+ // To read next page we initialize the cursor:
+ cursor = transactions.pageInfo.endCursor;
+ // TODO: rate limiting
+ await sleep(1000);
+ }
+
+}
+
+main(client)
+ .then(() => {
+ process.exit(0)
+ })
+ .catch(error => {
+ console.error(error);
+ process.exit(1);
+ })
+
+
+
+// This helper function is used for limiting request rate
+function sleep(ms: number) { return new Promise(r => setTimeout(r, ms)) }
+
+
diff --git a/tests/tsconfig.json b/tests/tsconfig.json
new file mode 100644
index 0000000..5d8c2da
--- /dev/null
+++ b/tests/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "es6",
+ "module": "commonjs",
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "resolveJsonModule": true,
+ "noImplicitAny": true,
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "outDir": "dist",
+ "baseUrl": ".",
+ "paths": {
+ "*": ["node_modules/*", "src/types/*"]
+ }
+ },
+ "include": ["src/**/*", "test/**/*"],
+ "exclude": ["node_modules", "src/**/*.spec.ts", "**/__mocks__"]
+}
diff --git a/up.sh b/up.sh
new file mode 100755
index 0000000..26bfe16
--- /dev/null
+++ b/up.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+echo "Starting Statsd"
+docker-compose -f deploy/statsd/docker-compose.yml up --build -d
+
+echo "Starting ArangoDB"
+docker-compose -f deploy/arangodb/docker-compose.yml up --build -d
+
+
+echo "Starting Kafka & Kafka Connect"
+docker-compose -f deploy/kafka/docker-compose.yml up --build -d
+
+
+echo "Starting Q-Server"
+docker-compose -f deploy/q-server/docker-compose.yml up --build -d
+
+
+echo "Starting Node"
+./deploy/ever-node/start_node.sh
+
+echo "Starting reverse proxy"
+docker-compose -f deploy/proxy/docker-compose.yml up --build -d