diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..af9865647 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[target.aarch64-unknown-linux-musl] +linker = "aarch64-linux-gnu-gcc" +rustflags = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lgcc" ] + +[target.x86_64-unknown-linux-musl] +rustflags = [ "-C", "target-feature=-crt-static" ] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 7c27032f2..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,30 +0,0 @@ -on: [push, pull_request] - -name: CI - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - - run: cargo test - linting: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - - run: rustup component add clippy --toolchain nightly - - run: cargo clippy - errors: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - - run: cargo check diff --git a/.github/workflows/grovedb.yml b/.github/workflows/grovedb.yml new file mode 100644 index 000000000..2785ec4ba --- /dev/null +++ b/.github/workflows/grovedb.yml @@ -0,0 +1,80 @@ +on: + workflow_dispatch: + pull_request: + branches: + - master + +name: GroveDB + +jobs: + test: + name: Tests + runs-on: ubuntu-latest + steps: + - name: Cancel previous runs + uses: styfle/cancel-workflow-action@0.9.1 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v2 + + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + + - run: cargo test + + linting: + name: Liniting + runs-on: ubuntu-latest + steps: + - name: Cancel previous runs + uses: styfle/cancel-workflow-action@0.9.1 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v2 + + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + default: true + components: clippy + + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-features + + errors: + name: Compilation errors + runs-on: ubuntu-latest + steps: + - name: Cancel previous runs + uses: styfle/cancel-workflow-action@0.9.1 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v2 + + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + default: true + + - run: cargo check + + security: + name: Dependencies security audit + runs-on: ubuntu-latest + steps: + - name: Cancel previous runs + uses: styfle/cancel-workflow-action@0.9.1 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v2 + + - uses: actions-rs/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 000000000..808a69bef --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,64 @@ +on: + workflow_dispatch: + pull_request: + branches: + - master + +name: Node.JS binding + +jobs: + test: + name: Tests + runs-on: ubuntu-latest + steps: + - name: Cancel previous runs + uses: styfle/cancel-workflow-action@0.9.1 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v2 + + - name: Setup Node.JS + uses: actions/setup-node@v2 + with: + node-version: '16' + + - name: Setup Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + default: true + + - name: Install NPM deps + run: npm ci + + - name: Run tests + run: npm test + + linting: + name: Linting + runs-on: ubuntu-latest + steps: + - name: Cancel previous runs + uses: styfle/cancel-workflow-action@0.9.1 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v2 + + - name: Setup Node.JS + uses: actions/setup-node@v2 + with: + node-version: '16' + + - name: Setup Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + default: true + + - name: Install NPM deps + run: npm ci + + - name: Run ES linter + run: npm run lint \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..ff1069124 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,186 @@ +name: Release + +on: + workflow_dispatch: + release: + types: + - published + +jobs: + build: + name: Build Node.JS binding + + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + arch: x86_64 + compiler: gnu + platform: unknown-linux +# TODO: Enable build for arm64 linux gnu +# - os: ubuntu-latest +# arch: aarch64 +# node_arch: arm64 +# compiler: gnu +# platform: unknown-linux +# build_dependencies: +# - gcc-aarch64-linux-gnu +# - binutils-aarch64-linux-gnu +# - clang + - os: ubuntu-latest + arch: x86_64 + compiler: musl + platform: unknown-linux + build_dependencies: + - musl-tools +# TODO: Enable build for arm64 linux musl +# - os: ubuntu-latest +# arch: aarch64 +# node_arch: arm64 +# compiler: musl +# platform: unknown-linux +# build_dependencies: +# - gcc-aarch64-linux-gnu +# - binutils-aarch64-linux-gnu +# - clang +# - musl-tools +# - musl +# - musl:arm64 + - os: macos-11 + arch: x86_64 + platform: apple-darwin + - os: macos-11 + arch: aarch64 + node_arch: arm64 + platform: apple-darwin + + runs-on: ${{ matrix.os }} + steps: + - name: Check out repo + uses: actions/checkout@v2 + + - name: Setup Node.JS + uses: actions/setup-node@v2 + with: + node-version: 16 + + - name: Install NPM deps + run: npm ci + + - name: Set target name + uses: actions/github-script@v5 + id: set-target + with: + script: | + let target = '${{ matrix.arch }}-${{ matrix.platform }}'; + + if ('${{ matrix.compiler }}') { + target += '-${{ matrix.compiler }}'; + } + + core.info(`Set target ${target}`); + + return target; + result-encoding: string + +# - name: Add arm64 architecture for apt +# if: ${{ matrix.os == 'ubuntu-latest' && matrix.arch == 'aarch64' }} +# run: sudo dpkg --add-architecture arm64 + + - name: Install build deps + if: ${{ matrix.os == 'ubuntu-latest' && matrix.build_dependencies && matrix.build_dependencies[0] }} + run: | + sudo apt-get update + sudo apt-get install ${{ join(matrix.build_dependencies, ' ') }} + + - name: Fix missing "musl-g++" for x86_64-unknown-linux-musl # https://github.com/rust-lang/cargo/issues/3359 + if: ${{ matrix.os == 'ubuntu-latest' && matrix.arch == 'x86_64' && matrix.compiler == 'musl' }} + run: sudo ln -s /bin/g++ /bin/musl-g++ + + - name: Setup Rust toolchain and target + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + default: true + target: ${{ steps.set-target.outputs.result }} + + - name: Set defualt target + uses: DamianReeves/write-file-action@v1.0 + with: + path: .cargo/config.toml + write-mode: append + contents: | + + [build] + target = "${{ steps.set-target.outputs.result }}" + + - name: Set LIBC env + uses: actions/github-script@v5 + id: set-libc + with: + script: | + let env = ''; + + if (${{ matrix.compiler == 'musl' }}) { + env = 'musl' + } + + core.info(`Set LIBC env to "${env}"`); + + return env; + result-encoding: string + + - name: Run tests + run: npm test + if: ${{ matrix.os != '' && matrix.arch != 'aarch64' }} # TODO Run test on Apple M1 + env: + LIBC: ${{ steps.set-libc.outputs.result }} + ARCH: ${{ matrix.node_arch }} # Overwrite current arch with target one + + - name: Build + run: npm run build:release + env: + LIBC: ${{ steps.set-libc.outputs.result }} + ARCH: ${{ matrix.node_arch }} # Overwrite current arch with target one + + - name: Upload prebuild artifacts + uses: actions/upload-artifact@v2 + with: + name: prebuilds + path: node-grove/prebuilds/ + + publish: + name: Publish NPM Package + needs: [build] + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + + - name: Check package version matches tag + uses: geritol/match-tag-to-package-version@0.2.0 + env: + TAG_PREFIX: v + + - name: Setup Node.JS + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + + - name: Install NPM deps + run: npm ci + + - name: Download prebuild artifacts + uses: actions/download-artifact@v2 + with: + name: prebuilds + path: node-grove/prebuilds + + - name: List prebuilds + run: ls -laR node-grove/prebuilds + + - name: NPM Publish + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 2c1bab50d..dd9e390e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ /target .idea Cargo.lock -index.node +node-grove/prebuilds node_modules .DS_Store -.DS_Store? +.DS_Store? \ No newline at end of file diff --git a/grovedb/src/lib.rs b/grovedb/src/lib.rs index 69cc55ab3..4a4d7a35b 100644 --- a/grovedb/src/lib.rs +++ b/grovedb/src/lib.rs @@ -7,6 +7,7 @@ mod transaction; use std::{cell::RefCell, collections::HashMap, path::Path, rc::Rc}; +use blake3; pub use merk::proofs::{query::QueryItem, Query}; use merk::{self, Merk}; use rs_merkle::{algorithms::Sha256, Hasher, MerkleTree}; @@ -18,7 +19,6 @@ use storage::{ }; pub use subtree::Element; use subtrees::Subtrees; -use blake3; // use crate::transaction::GroveDbTransaction; // pub use transaction::GroveDbTransaction; @@ -58,8 +58,10 @@ pub enum Error { DbIsInReadonlyMode, } -pub struct PathQuery<'a> { - path: &'a [&'a [u8]], +#[derive(Debug)] +pub struct PathQuery { + // TODO: Make generic over path type + path: Vec>, query: SizedQuery, } @@ -67,6 +69,7 @@ pub struct PathQuery<'a> { // limit should be applied to the elements returned by the subquery // offset should be applied to the first item that will subqueried (first in the // case of a range) +#[derive(Debug)] pub struct SizedQuery { query: Query, limit: Option, @@ -74,11 +77,7 @@ pub struct SizedQuery { } impl SizedQuery { - pub fn new( - query: Query, - limit: Option, - offset: Option, - ) -> SizedQuery { + pub fn new(query: Query, limit: Option, offset: Option) -> SizedQuery { SizedQuery { query, limit, @@ -87,12 +86,12 @@ impl SizedQuery { } } -impl PathQuery<'_> { - pub fn new<'a>(path: &'a [&'a [u8]], query: SizedQuery) -> PathQuery<'a> { +impl PathQuery { + pub fn new(path: Vec>, query: SizedQuery) -> PathQuery { PathQuery { path, query } } - pub fn new_unsized<'a>(path: &'a [&'a [u8]], query: Query) -> PathQuery<'a> { + pub fn new_unsized(path: Vec>, query: Query) -> PathQuery { let query = SizedQuery::new(query, None, None); PathQuery { path, query } } @@ -272,7 +271,8 @@ impl GroveDb { self.get_subtrees() .insert_temp_tree(parent_path, upper_tree, transaction); } else { - self.get_subtrees().insert_temp_tree(path, upper_tree, transaction); + self.get_subtrees() + .insert_temp_tree(path, upper_tree, transaction); } path = parent_path; @@ -445,7 +445,7 @@ impl GroveDb { /// [`GroveDb::start_transaction`] pub fn abort_transaction( &mut self, - db_transaction: OptimisticTransactionDBTransaction, + _db_transaction: OptimisticTransactionDBTransaction, ) -> Result<(), Error> { // Cloning all the trees to maintain to rollback transactional changes self.cleanup_transactional_data(); diff --git a/grovedb/src/operations/get.rs b/grovedb/src/operations/get.rs index 84248dac1..7ae358a30 100644 --- a/grovedb/src/operations/get.rs +++ b/grovedb/src/operations/get.rs @@ -77,7 +77,7 @@ impl GroveDb { // then use this to get merk. let merk_result; if path.is_empty() { - merk_result = self.get_subtrees().get(&[key], transaction)?; + merk_result = self.get_subtrees().get(&[key], transaction)?; } else { merk_result = self.get_subtrees().get(path, transaction)?; } @@ -85,8 +85,8 @@ impl GroveDb { let (merk, prefix) = merk_result; let elem; - if path.is_empty(){ - elem = Ok(Element::Tree(merk.root_hash())); + if path.is_empty() { + elem = Ok(Element::Tree(merk.root_hash())); } else { elem = Element::get(&merk, key); } @@ -182,15 +182,19 @@ impl GroveDb { transaction: Option<&OptimisticTransactionDBTransaction>, // subtrees: &HashMap, Merk>, ) -> Result<(Vec, u16), Error> { - let path = path_query.path; - let (merk, prefix) = subtrees.get(path, transaction)?; + let path_slices = path_query + .path + .iter() + .map(|x| x.as_slice()) + .collect::>(); + let (merk, prefix) = subtrees.get(path_slices.as_slice(), transaction)?; let elem = Element::get_path_query(&merk, path_query, Some(&subtrees)); - if let Some(prefix) = prefix{ + if let Some(prefix) = prefix { subtrees.insert_temp_tree_with_prefix(prefix, merk, transaction); } else { - subtrees.insert_temp_tree(path, merk, transaction); + subtrees.insert_temp_tree(path_slices.as_slice(), merk, transaction); } elem diff --git a/grovedb/src/operations/insert.rs b/grovedb/src/operations/insert.rs index 67c5bee97..8f891ecf1 100644 --- a/grovedb/src/operations/insert.rs +++ b/grovedb/src/operations/insert.rs @@ -27,10 +27,8 @@ impl GroveDb { element: Element, transaction: Option<&'b ::DBTransaction<'b>>, ) -> Result<(), Error> { - if let None = transaction { - if self.is_readonly { - return Err(Error::DbIsInReadonlyMode); - } + if transaction.is_none() && self.is_readonly { + return Err(Error::DbIsInReadonlyMode); } match element { @@ -55,7 +53,7 @@ impl GroveDb { .get(path, transaction) .map_err(|_| Error::InvalidPath("no subtree found under that path"))?; element.insert(&mut merk, key, transaction)?; - if let Some(prefix) = prefix{ + if let Some(prefix) = prefix { self.get_subtrees() .insert_temp_tree_with_prefix(prefix, merk, transaction); } else { @@ -80,7 +78,6 @@ impl GroveDb { } } - // Open Merk and put handle into `subtrees` dictionary accessible by its // compressed path let (subtree_prefix, subtree_merk) = create_merk_with_prefix(self.db.clone(), &[], key)?; @@ -147,7 +144,7 @@ impl GroveDb { // need to mark key as taken in the upper tree element.insert(&mut merk, key, transaction)?; - if let Some(prefix) = prefix{ + if let Some(prefix) = prefix { self.get_subtrees() .insert_temp_tree_with_prefix(prefix, merk, transaction); } else { diff --git a/grovedb/src/operations/proof.rs b/grovedb/src/operations/proof.rs index 4a945a8ac..8c628cf54 100644 --- a/grovedb/src/operations/proof.rs +++ b/grovedb/src/operations/proof.rs @@ -6,15 +6,15 @@ // use crate::{Element, Error, GroveDb, PathQuery, Proof, Query}; // // impl GroveDb { -// pub fn proof(&mut self, proof_queries: Vec) -> Result, Error> { -// // To prove a path we need to return a proof for each node on the path including -// // the root. With multiple paths, nodes can overlap i.e two or more paths can -// // share the same nodes. We should only have one proof for each node, -// // if a node forks into multiple relevant paths then we should create a -// // combined proof for that node with all the relevant keys -// let mut query_paths = Vec::new(); -// let mut intermediate_proof_spec: HashMap, Query> = HashMap::new(); -// let mut root_keys: Vec> = Vec::new(); +// pub fn proof(&mut self, proof_queries: Vec) -> Result, +// Error> { // To prove a path we need to return a proof for each node +// on the path including // the root. With multiple paths, nodes can +// overlap i.e two or more paths can // share the same nodes. We should +// only have one proof for each node, // if a node forks into multiple +// relevant paths then we should create a // combined proof for that +// node with all the relevant keys let mut query_paths = Vec::new(); +// let mut intermediate_proof_spec: HashMap, Query> = +// HashMap::new(); let mut root_keys: Vec> = Vec::new(); // let mut proofs: HashMap, Vec> = HashMap::new(); // // // For each unique node including the root @@ -32,17 +32,18 @@ // while let Some((key, path_slice)) = split_path { // if path_slice.is_empty() { // // We have gotten to the root node -// let compressed_path = GroveDb::compress_subtree_key(&[], Some(key)); -// root_keys.push(compressed_path); +// let compressed_path = GroveDb::compress_subtree_key(&[], +// Some(key)); root_keys.push(compressed_path); // } else { -// let compressed_path = GroveDb::compress_subtree_key(path_slice, None); -// if let Some(path_query) = intermediate_proof_spec.get_mut(&compressed_path) { +// let compressed_path = +// GroveDb::compress_subtree_key(path_slice, None); if let +// Some(path_query) = intermediate_proof_spec.get_mut(&compressed_path) { // path_query.insert_key(key.to_vec()); // } else { // let mut path_query = Query::new(); // path_query.insert_key(key.to_vec()); -// intermediate_proof_spec.insert(compressed_path, path_query); -// } +// intermediate_proof_spec.insert(compressed_path, +// path_query); } // } // split_path = path_slice.split_last(); // } @@ -58,24 +59,25 @@ // for proof_query in proof_queries { // let path = proof_query.path; // -// // If there is a subquery with a limit it's possible that we only need a reduced -// // proof for this leaf. +// // If there is a subquery with a limit it's possible that we only +// need a reduced // proof for this leaf. // let reduced_proof_query = proof_query; // // // First we must get elements // -// if let Some(subquery_key) = reduced_proof_query.query.query.subquery_key.clone() { -// self.get_path_queries_raw(&[&reduced_proof_query], None)?; +// if let Some(subquery_key) = +// reduced_proof_query.query.query.subquery_key.clone() { +// self.get_path_queries_raw(&[&reduced_proof_query], None)?; // // let mut path_vec = path.to_vec(); // path_vec.push(subquery_key.as_slice()); -// let compressed_path = GroveDb::compress_subtree_key(path_vec.as_slice(), None); -// } +// let compressed_path = +// GroveDb::compress_subtree_key(path_vec.as_slice(), None); } // // // Now we must insert the final proof for the sub leaves // let compressed_path = GroveDb::compress_subtree_key(path, None); -// let proof = self.prove_path_item(&compressed_path, reduced_proof_query)?; -// proofs.insert(compressed_path, proof); +// let proof = self.prove_path_item(&compressed_path, +// reduced_proof_query)?; proofs.insert(compressed_path, proof); // } // // // Construct the root proof @@ -97,7 +99,8 @@ // }; // // let seralized_proof = bincode::serialize(&proof) -// .map_err(|_| Error::CorruptedData(String::from("unable to serialize proof")))?; +// .map_err(|_| Error::CorruptedData(String::from("unable to +// serialize proof")))?; // // Ok(seralized_proof) // } @@ -132,8 +135,8 @@ // } // } // -// fn prove_item(&self, path: &Vec, query: Query) -> Result, Error> { -// let merk = self +// fn prove_item(&self, path: &Vec, query: Query) -> Result, +// Error> { let merk = self // .subtrees // .get(path) // .ok_or(Error::InvalidPath("no subtree found under that path"))?; @@ -145,10 +148,11 @@ // Ok(proof_result) // } // -// pub fn execute_proof(proof: Vec) -> Result<([u8; 32], HashMap, Map>), Error> { -// // Deserialize the proof +// pub fn execute_proof(proof: Vec) -> Result<([u8; 32], +// HashMap, Map>), Error> { // Deserialize the proof // let proof: Proof = bincode::deserialize(&proof) -// .map_err(|_| Error::CorruptedData(String::from("unable to deserialize proof")))?; +// .map_err(|_| Error::CorruptedData(String::from("unable to +// deserialize proof")))?; // // // Required to execute the root proof // let mut root_keys_index: Vec = Vec::new(); @@ -162,9 +166,10 @@ // // For each query path, get the result map after execution // // and store hash + index for later root proof execution // let root_key = &path[0]; -// let (hash, proof_result_map) = GroveDb::execute_path(&path, &proof.proofs)?; -// let compressed_root_key_path = GroveDb::compress_subtree_key(&[], Some(root_key)); -// let compressed_query_path = GroveDb::compress_subtree_key(&path, None); +// let (hash, proof_result_map) = GroveDb::execute_path(&path, +// &proof.proofs)?; let compressed_root_key_path = +// GroveDb::compress_subtree_key(&[], Some(root_key)); let +// compressed_query_path = GroveDb::compress_subtree_key(&path, None); // // let index = proof // .root_leaf_keys @@ -178,14 +183,14 @@ // result_map.insert(compressed_query_path, proof_result_map); // } // -// let root_proof = match MerkleProof::::try_from(proof.root_proof) { -// Ok(proof) => Ok(proof), -// Err(_) => Err(Error::InvalidProof("Invalid proof element")), -// }?; +// let root_proof = match +// MerkleProof::::try_from(proof.root_proof) { Ok(proof) => +// Ok(proof), Err(_) => Err(Error::InvalidProof("Invalid proof +// element")), }?; // // let root_hash = -// match root_proof.root(&root_keys_index, &root_hashes, proof.root_leaf_keys.len()) { -// Ok(hash) => Ok(hash), +// match root_proof.root(&root_keys_index, &root_hashes, +// proof.root_leaf_keys.len()) { Ok(hash) => Ok(hash), // Err(_) => Err(Error::InvalidProof("Invalid proof element")), // }?; // @@ -194,10 +199,10 @@ // // // Given a query path and a set of proofs // // execute_path validates that the nodes represented by the paths -// // are connected to one another i.e root hash of child node is in parent node -// // at the correct key. -// // If path is valid, it returns the root hash of topmost merk and result map of -// // leaf merk. +// // are connected to one another i.e root hash of child node is in parent +// node // at the correct key. +// // If path is valid, it returns the root hash of topmost merk and result +// map of // leaf merk. // fn execute_path( // path: &[&[u8]], // proofs: &HashMap, Vec>, @@ -208,8 +213,8 @@ // .ok_or(Error::InvalidPath("Bad path"))?; // // // Execute the leaf merk proof -// let (mut last_root_hash, result_map) = match merk::execute_proof(&proof[..]) { -// Ok(result) => Ok(result), +// let (mut last_root_hash, result_map) = match +// merk::execute_proof(&proof[..]) { Ok(result) => Ok(result), // Err(_) => Err(Error::InvalidPath("Invalid proof element")), // }?; // @@ -217,20 +222,21 @@ // let mut split_path = path.split_last(); // while let Some((key, path_slice)) = split_path { // if !path_slice.is_empty() { -// let compressed_path = GroveDb::compress_subtree_key(path_slice, None); -// let proof = proofs -// .get(&compressed_path) +// let compressed_path = +// GroveDb::compress_subtree_key(path_slice, None); let proof = +// proofs .get(&compressed_path) // .ok_or(Error::InvalidPath("Bad path"))?; // // let proof_result = match merk::execute_proof(&proof[..]) { // Ok(result) => Ok(result), -// Err(_) => Err(Error::InvalidPath("Invalid proof element")), -// }?; +// Err(_) => Err(Error::InvalidPath("Invalid proof +// element")), }?; // // let result_map = proof_result.1; // // TODO: Handle the error better here // let elem: Element = -// bincode::deserialize(result_map.get(key).unwrap().unwrap()).unwrap(); +// +// bincode::deserialize(result_map.get(key).unwrap().unwrap()).unwrap(); // let merk_root_hash = match elem { // Element::Tree(hash) => Ok(hash), // _ => Err(Error::InvalidProof( diff --git a/grovedb/src/subtree.rs b/grovedb/src/subtree.rs index 9fb03ba4c..b380cf7a7 100644 --- a/grovedb/src/subtree.rs +++ b/grovedb/src/subtree.rs @@ -56,9 +56,10 @@ impl Element { let element = bincode::deserialize( merk.get(key) .map_err(|e| Error::CorruptedData(e.to_string()))? - .ok_or(Error::InvalidPathKey( - format!("key not found in Merk: {}", hex::encode(key)), - ))? + .ok_or(Error::InvalidPathKey(format!( + "key not found in Merk: {}", + hex::encode(key) + )))? .as_slice(), ) .map_err(|_| Error::CorruptedData(String::from("unable to deserialize element")))?; @@ -137,11 +138,15 @@ impl Element { if let Some(subquery_key) = &subquery_key_option { path_vec.push(subquery_key.as_slice()); } + let (inner_merk, prefix) = subtrees .get(path_vec.as_slice(), None) .map_err(|_| Error::InvalidPath("no subtree found under that path"))?; + let inner_query = SizedQuery::new(subquery, *limit, *offset); - let inner_path_query = PathQuery::new(path_vec.as_slice(), inner_query); + let path_vec_owned = path_vec.iter().map(|x| x.to_vec()).collect(); + let inner_path_query = PathQuery::new(path_vec_owned, inner_query); + let (mut sub_elements, skipped) = Element::get_path_query(&inner_merk, &inner_path_query, subtrees_option)?; @@ -296,10 +301,15 @@ impl Element { // subtrees: Option<&HashMap, Merk>>, subtrees: Option<&Subtrees>, ) -> Result<(Vec, u16), Error> { + let path_slices = path_query + .path + .iter() + .map(|x| x.as_slice()) + .collect::>(); Element::get_query_apply_function( merk, &path_query.query, - Some(path_query.path), + Some(path_slices.as_slice()), subtrees, Element::path_query_push, ) diff --git a/grovedb/src/tests.rs b/grovedb/src/tests.rs index 6fe8db714..6cafc48fe 100644 --- a/grovedb/src/tests.rs +++ b/grovedb/src/tests.rs @@ -404,10 +404,11 @@ fn test_root_tree_leafs_are_noted() { // // Get grovedb proof // let proof = temp_db // .proof(vec![ -// PathQuery::new_unsized(&[TEST_LEAF, b"innertree"], path_one_query), -// PathQuery::new_unsized(&[ANOTHER_TEST_LEAF, b"innertree3"], path_two_query), -// PathQuery::new_unsized(&[ANOTHER_TEST_LEAF, b"innertree2"], path_three_query), -// ]) +// PathQuery::new_unsized(&[TEST_LEAF, b"innertree"], +// path_one_query), PathQuery::new_unsized(&[ANOTHER_TEST_LEAF, +// b"innertree3"], path_two_query), +// PathQuery::new_unsized(&[ANOTHER_TEST_LEAF, b"innertree2"], +// path_three_query), ]) // .unwrap(); // // // Deserialize the proof @@ -423,23 +424,28 @@ fn test_root_tree_leafs_are_noted() { // // root is repeated three times and another_test_leaf is repeated twice // // Accounting for duplication, there are 6 unique nodes // // root, test_leaf, another_test_leaf, innertree, innertree2, innertree3 -// // proof.proofs contains all nodes except the root so we expect 5 sub proofs -// assert_eq!(proof.proofs.len(), 5); +// // proof.proofs contains all nodes except the root so we expect 5 sub +// proofs assert_eq!(proof.proofs.len(), 5); // -// // Check that all the subproofs were constructed correctly for each path and -// // subpath -// let path_one_as_vec = GroveDb::compress_subtree_key(&[TEST_LEAF, b"innertree"], None); -// let path_two_as_vec = GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, b"innertree3"], None); +// // Check that all the subproofs were constructed correctly for each path +// and // subpath +// let path_one_as_vec = GroveDb::compress_subtree_key(&[TEST_LEAF, +// b"innertree"], None); let path_two_as_vec = +// GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, b"innertree3"], None); // let path_three_as_vec = -// GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, b"innertree2"], None); -// let test_leaf_path_as_vec = GroveDb::compress_subtree_key(&[TEST_LEAF], None); -// let another_test_leaf_path_as_vec = GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF], None); +// GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, b"innertree2"], +// None); let test_leaf_path_as_vec = +// GroveDb::compress_subtree_key(&[TEST_LEAF], None); +// let another_test_leaf_path_as_vec = +// GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF], None); // // let proof_for_path_one = proof.proofs.get(&path_one_as_vec).unwrap(); // let proof_for_path_two = proof.proofs.get(&path_two_as_vec).unwrap(); // let proof_for_path_three = proof.proofs.get(&path_three_as_vec).unwrap(); -// let proof_for_test_leaf = proof.proofs.get(&test_leaf_path_as_vec).unwrap(); -// let proof_for_another_test_leaf = proof.proofs.get(&another_test_leaf_path_as_vec).unwrap(); +// let proof_for_test_leaf = +// proof.proofs.get(&test_leaf_path_as_vec).unwrap(); +// let proof_for_another_test_leaf = +// proof.proofs.get(&another_test_leaf_path_as_vec).unwrap(); // // // Assert path 1 proof // let mut proof_query = Query::new(); @@ -488,10 +494,11 @@ fn test_root_tree_leafs_are_noted() { // ); // // // Check that the root proof is valid -// // Root proof should contain proof for both test_leaf and another_test_leaf -// let test_leaf_root_key = GroveDb::compress_subtree_key(&[], Some(TEST_LEAF)); -// let another_test_leaf_root_key = GroveDb::compress_subtree_key(&[], Some(ANOTHER_TEST_LEAF)); -// assert_eq!( +// // Root proof should contain proof for both test_leaf and +// another_test_leaf let test_leaf_root_key = +// GroveDb::compress_subtree_key(&[], Some(TEST_LEAF)); +// let another_test_leaf_root_key = GroveDb::compress_subtree_key(&[], +// Some(ANOTHER_TEST_LEAF)); assert_eq!( // proof.root_proof, // root_tree // .proof(&[ @@ -601,10 +608,12 @@ fn test_root_tree_leafs_are_noted() { // // // Assert correct result object // // Proof query was for two keys key1 and key2 -// let path_as_vec = GroveDb::compress_subtree_key(&[TEST_LEAF, b"innertree"], None); -// let result_map = result_maps.get(&path_as_vec).unwrap(); -// let elem_1: Element = bincode::deserialize(result_map.get(b"key1").unwrap().unwrap()).unwrap(); -// let elem_2: Element = bincode::deserialize(result_map.get(b"key2").unwrap().unwrap()).unwrap(); +// let path_as_vec = GroveDb::compress_subtree_key(&[TEST_LEAF, +// b"innertree"], None); let result_map = +// result_maps.get(&path_as_vec).unwrap(); let elem_1: Element = +// bincode::deserialize(result_map.get(b"key1").unwrap().unwrap()).unwrap(); +// let elem_2: Element = +// bincode::deserialize(result_map.get(b"key2").unwrap().unwrap()).unwrap(); // assert_eq!(elem_1, Element::Item(b"value1".to_vec())); // assert_eq!(elem_2, Element::Item(b"value2".to_vec())); // @@ -618,9 +627,9 @@ fn test_root_tree_leafs_are_noted() { // // Get grovedb proof // let proof = temp_db // .proof(vec![ -// PathQuery::new_unsized(&[ANOTHER_TEST_LEAF, b"innertree3"], path_two_query), -// PathQuery::new_unsized(&[ANOTHER_TEST_LEAF, b"innertree2"], path_three_query), -// ]) +// PathQuery::new_unsized(&[ANOTHER_TEST_LEAF, b"innertree3"], +// path_two_query), PathQuery::new_unsized(&[ANOTHER_TEST_LEAF, +// b"innertree2"], path_three_query), ]) // .unwrap(); // // // Assert correct root hash @@ -628,14 +637,16 @@ fn test_root_tree_leafs_are_noted() { // assert_eq!(temp_db.root_tree.root().unwrap(), root_hash); // // // Assert correct result object -// let path_one_as_vec = GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, b"innertree3"], None); -// let result_map = result_maps.get(&path_one_as_vec).unwrap(); -// let elem: Element = bincode::deserialize(result_map.get(b"key4").unwrap().unwrap()).unwrap(); +// let path_one_as_vec = GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, +// b"innertree3"], None); let result_map = +// result_maps.get(&path_one_as_vec).unwrap(); let elem: Element = +// bincode::deserialize(result_map.get(b"key4").unwrap().unwrap()).unwrap(); // assert_eq!(elem, Element::Item(b"value4".to_vec())); // -// let path_two_as_vec = GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, b"innertree2"], None); -// let result_map = result_maps.get(&path_two_as_vec).unwrap(); -// let elem: Element = bincode::deserialize(result_map.get(b"key3").unwrap().unwrap()).unwrap(); +// let path_two_as_vec = GroveDb::compress_subtree_key(&[ANOTHER_TEST_LEAF, +// b"innertree2"], None); let result_map = +// result_maps.get(&path_two_as_vec).unwrap(); let elem: Element = +// bincode::deserialize(result_map.get(b"key3").unwrap().unwrap()).unwrap(); // assert_eq!(elem, Element::Item(b"value3".to_vec())); // } @@ -1272,15 +1283,15 @@ fn test_get_full_query() { ) .expect("successful value insert"); - let path1 = vec![TEST_LEAF, b"key1"]; - let path2 = vec![TEST_LEAF, b"key2"]; + let path1 = vec![TEST_LEAF.to_vec(), b"key1".to_vec()]; + let path2 = vec![TEST_LEAF.to_vec(), b"key2".to_vec()]; let mut query1 = Query::new(); let mut query2 = Query::new(); query1.insert_range_inclusive(b"key3".to_vec()..=b"key4".to_vec()); query2.insert_key(b"key6".to_vec()); - let path_query1 = PathQuery::new_unsized(&path1, query1); - let path_query2 = PathQuery::new_unsized(&path2, query2); + let path_query1 = PathQuery::new_unsized(path1, query1); + let path_query2 = PathQuery::new_unsized(path2, query2); assert_eq!( db.get_path_queries_raw(&[&path_query1, &path_query2], None) @@ -1518,7 +1529,11 @@ fn populate_tree_by_reference_for_non_unique_range_subquery(db: &mut TempGroveDb db.insert( &[TEST_LEAF, b"1", i_vec.clone().as_slice(), b"\0"], random_key.to_vec(), - Element::Reference(vec![TEST_LEAF.to_vec(), b"\0".to_vec(), random_key.to_vec()]), + Element::Reference(vec![ + TEST_LEAF.to_vec(), + b"\0".to_vec(), + random_key.to_vec(), + ]), None, ) .expect("successful value insert"); @@ -1587,7 +1602,7 @@ fn test_get_range_query_with_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range((1988 as u32).to_be_bytes().to_vec()..(1992 as u32).to_be_bytes().to_vec()); @@ -1598,7 +1613,7 @@ fn test_get_range_query_with_non_unique_subquery() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1620,7 +1635,7 @@ fn test_get_range_query_with_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range((1988 as u32).to_be_bytes().to_vec()..(1992 as u32).to_be_bytes().to_vec()); @@ -1628,7 +1643,7 @@ fn test_get_range_query_with_unique_subquery() { query.set_subquery_key(subquery_key); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1648,7 +1663,7 @@ fn test_get_range_query_with_unique_subquery_on_references() { let mut db = make_grovedb(); populate_tree_by_reference_for_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF, b"1"]; + let path = vec![TEST_LEAF.to_vec(), b"1".to_vec()]; let mut query = Query::new(); query.insert_range((1988 as u32).to_be_bytes().to_vec()..(1992 as u32).to_be_bytes().to_vec()); @@ -1656,7 +1671,7 @@ fn test_get_range_query_with_unique_subquery_on_references() { query.set_subquery_key(subquery_key); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1676,7 +1691,7 @@ fn test_get_range_inclusive_query_with_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_inclusive( (1988 as u32).to_be_bytes().to_vec()..=(1995 as u32).to_be_bytes().to_vec(), @@ -1689,7 +1704,7 @@ fn test_get_range_inclusive_query_with_non_unique_subquery() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1711,7 +1726,7 @@ fn test_get_range_inclusive_query_with_non_unique_subquery_on_references() { let mut db = make_grovedb(); populate_tree_by_reference_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF, b"1"]; + let path = vec![TEST_LEAF.to_vec(), b"1".to_vec()]; let mut query = Query::new(); query.insert_range_inclusive( (1988 as u32).to_be_bytes().to_vec()..=(1995 as u32).to_be_bytes().to_vec(), @@ -1724,7 +1739,7 @@ fn test_get_range_inclusive_query_with_non_unique_subquery_on_references() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1746,7 +1761,7 @@ fn test_get_range_inclusive_query_with_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_inclusive( (1988 as u32).to_be_bytes().to_vec()..=(1995 as u32).to_be_bytes().to_vec(), @@ -1756,7 +1771,7 @@ fn test_get_range_inclusive_query_with_unique_subquery() { query.set_subquery_key(subquery_key); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1776,7 +1791,7 @@ fn test_get_range_from_query_with_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_from((1995 as u32).to_be_bytes().to_vec()..); @@ -1787,7 +1802,7 @@ fn test_get_range_from_query_with_non_unique_subquery() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1809,7 +1824,7 @@ fn test_get_range_from_query_with_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_from((1995 as u32).to_be_bytes().to_vec()..); @@ -1817,7 +1832,7 @@ fn test_get_range_from_query_with_unique_subquery() { query.set_subquery_key(subquery_key); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1837,7 +1852,7 @@ fn test_get_range_to_query_with_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_to(..(1995 as u32).to_be_bytes().to_vec()); @@ -1848,7 +1863,7 @@ fn test_get_range_to_query_with_non_unique_subquery() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1870,7 +1885,7 @@ fn test_get_range_to_query_with_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_to(..(1995 as u32).to_be_bytes().to_vec()); @@ -1878,7 +1893,7 @@ fn test_get_range_to_query_with_unique_subquery() { query.set_subquery_key(subquery_key); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1898,7 +1913,7 @@ fn test_get_range_to_inclusive_query_with_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_to_inclusive(..=(1995 as u32).to_be_bytes().to_vec()); @@ -1909,7 +1924,7 @@ fn test_get_range_to_inclusive_query_with_non_unique_subquery() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1931,7 +1946,7 @@ fn test_get_range_to_inclusive_query_with_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_to_inclusive(..=(1995 as u32).to_be_bytes().to_vec()); @@ -1939,7 +1954,7 @@ fn test_get_range_to_inclusive_query_with_unique_subquery() { query.set_subquery_key(subquery_key); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1959,7 +1974,7 @@ fn test_get_range_after_query_with_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_after((1995 as u32).to_be_bytes().to_vec()..); @@ -1970,7 +1985,7 @@ fn test_get_range_after_query_with_non_unique_subquery() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -1992,7 +2007,7 @@ fn test_get_range_after_to_query_with_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_after_to( (1995 as u32).to_be_bytes().to_vec()..(1997 as u32).to_be_bytes().to_vec(), @@ -2005,7 +2020,7 @@ fn test_get_range_after_to_query_with_non_unique_subquery() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -2027,7 +2042,7 @@ fn test_get_range_after_to_inclusive_query_with_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_after_to_inclusive( (1995 as u32).to_be_bytes().to_vec()..=(1997 as u32).to_be_bytes().to_vec(), @@ -2040,7 +2055,7 @@ fn test_get_range_after_to_inclusive_query_with_non_unique_subquery() { query.set_subquery_key(subquery_key); query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, _) = db .get_path_query(&path_query, None) @@ -2062,7 +2077,7 @@ fn test_get_range_inclusive_query_with_double_non_unique_subquery() { let mut db = make_grovedb(); populate_tree_for_non_unique_double_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new(); query.insert_range_inclusive( (3 as u32).to_be_bytes().to_vec()..=(4 as u32).to_be_bytes().to_vec(), @@ -2084,7 +2099,7 @@ fn test_get_range_inclusive_query_with_double_non_unique_subquery() { query.set_subquery(subquery); - let path_query = PathQuery::new_unsized(&path, query.clone()); + let path_query = PathQuery::new_unsized(path, query.clone()); let (elements, skipped) = db .get_path_query(&path_query, None) @@ -2104,7 +2119,7 @@ fn test_get_range_query_with_limit_and_offset() { let mut db = make_grovedb(); populate_tree_for_non_unique_range_subquery(&mut db); - let path = vec![TEST_LEAF]; + let path = vec![TEST_LEAF.to_vec()]; let mut query = Query::new_with_direction(true); query.insert_range((1990 as u32).to_be_bytes().to_vec()..(1995 as u32).to_be_bytes().to_vec()); @@ -2116,7 +2131,7 @@ fn test_get_range_query_with_limit_and_offset() { query.set_subquery(subquery.clone()); // Baseline query: no offset or limit + left to right - let path_query = PathQuery::new(&path, SizedQuery::new(query.clone(), None, None)); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query.clone(), None, None)); let (elements, _) = db .get_path_query(&path_query, None) @@ -2140,7 +2155,7 @@ fn test_get_range_query_with_limit_and_offset() { query.left_to_right = false; // Baseline query: no offset or limit + right to left - let path_query = PathQuery::new(&path, SizedQuery::new(query.clone(), None, None)); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query.clone(), None, None)); let (elements, _) = db .get_path_query(&path_query, None) @@ -2164,7 +2179,7 @@ fn test_get_range_query_with_limit_and_offset() { query.left_to_right = true; // Limit the result to just 55 elements - let path_query = PathQuery::new(&path, SizedQuery::new(query.clone(), Some(55), None)); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query.clone(), Some(55), None)); let (elements, _) = db .get_path_query(&path_query, None) @@ -2186,7 +2201,7 @@ fn test_get_range_query_with_limit_and_offset() { // Limit the result set to 60 elements but skip the first 14 elements let path_query = PathQuery::new( - &path, + path.clone(), SizedQuery::new(query.clone(), Some(60), Some(14)), ); @@ -2217,7 +2232,7 @@ fn test_get_range_query_with_limit_and_offset() { // Limit the result set to 60 element but skip first 10 elements (this time // right to left) let path_query = PathQuery::new( - &path, + path.clone(), SizedQuery::new(query.clone(), Some(60), Some(10)), ); @@ -2245,7 +2260,7 @@ fn test_get_range_query_with_limit_and_offset() { // Offset bigger than elements in range let path_query = PathQuery::new( - &path, + path.clone(), SizedQuery::new(query.clone(), None, Some(5000)), ); @@ -2260,7 +2275,7 @@ fn test_get_range_query_with_limit_and_offset() { // Limit bigger than elements in range let path_query = PathQuery::new( - &path, + path.clone(), SizedQuery::new(query.clone(), Some(5000), None), ); @@ -2279,10 +2294,7 @@ fn test_get_range_query_with_limit_and_offset() { query.set_subquery_key(subquery_key.clone()); - let path_query = PathQuery::new( - &path, - SizedQuery::new(query.clone(), Some(5), Some(2)), - ); + let path_query = PathQuery::new(path, SizedQuery::new(query.clone(), Some(5), Some(2))); let (elements, _) = db .get_path_query(&path_query, None) diff --git a/merk/Cargo.toml b/merk/Cargo.toml index b82930f21..19f589fe8 100644 --- a/merk/Cargo.toml +++ b/merk/Cargo.toml @@ -15,7 +15,7 @@ anyhow = "1.0.51" failure = "0.1.8" [dependencies.time] -version = "0.1.42" +version = "0.3.6" optional = true [dependencies.hex] diff --git a/merk/src/merk/mod.rs b/merk/src/merk/mod.rs index 67c95030e..11f131d1a 100644 --- a/merk/src/merk/mod.rs +++ b/merk/src/merk/mod.rs @@ -212,12 +212,7 @@ where /// check adds some overhead, so if you are sure your batch is sorted and /// unique you can use the unsafe `prove_unchecked` for a small performance /// gain. - pub fn prove( - &self, - query: Query, - limit: Option, - offset: Option, - ) -> Result> { + pub fn prove(&self, query: Query, limit: Option, offset: Option) -> Result> { let left_to_right = query.left_to_right; self.prove_unchecked(query, limit, offset, left_to_right) } diff --git a/merk/src/proofs/query/mod.rs b/merk/src/proofs/query/mod.rs index 5b970a498..ac87c1580 100644 --- a/merk/src/proofs/query/mod.rs +++ b/merk/src/proofs/query/mod.rs @@ -1,6 +1,11 @@ mod map; -use std::{cmp::{max, min, Ordering}, cmp, collections::BTreeSet, ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}}; +use std::{ + cmp, + cmp::{max, min, Ordering}, + collections::BTreeSet, + ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}, +}; use anyhow::{bail, Result}; pub use map::*; @@ -13,7 +18,7 @@ use crate::tree::{Fetch, Hash, Link, RefWalker}; /// `Query` represents one or more keys or ranges of keys, which can be used to /// resolve a proof which will include all of the requested values. -#[derive(Default, Clone)] +#[derive(Debug, Default, Clone)] pub struct Query { items: BTreeSet, pub subquery_key: Option>, @@ -197,7 +202,7 @@ impl> From> for Query { items, subquery_key: None, subquery: None, - left_to_right: true + left_to_right: true, } } } @@ -470,11 +475,11 @@ impl QueryItem { for (ai, bi) in a.iter().zip(b.iter()) { match ai.cmp(&bi) { Ordering::Equal => continue, - ord => return ord + ord => return ord, } } - /* if every single element was equal, compare length */ + // if every single element was equal, compare length a.len().cmp(&b.len()) } @@ -580,14 +585,14 @@ impl QueryItem { match QueryItem::compare(key, end) { Ordering::Less => true, Ordering::Equal => true, - Ordering::Greater => false + Ordering::Greater => false, } } else { let start = range_inclusive.start().as_slice(); match QueryItem::compare(key, start) { Ordering::Less => false, Ordering::Equal => false, - Ordering::Greater => true + Ordering::Greater => true, } } } diff --git a/node-grove/.eslintrc b/node-grove/.eslintrc new file mode 100644 index 000000000..bd1f5179e --- /dev/null +++ b/node-grove/.eslintrc @@ -0,0 +1,36 @@ +{ + "extends": "airbnb-base", + "env": { + "es2021": true, + "node": true, + "mocha": true + }, + "rules": { + "no-plusplus": 0, + "eol-last": [ + "error", + "always" + ], + "no-continue": "off", + "class-methods-use-this": "off", + "no-await-in-loop": "off", + "no-restricted-syntax": [ + "error", + { + "selector": "LabeledStatement", + "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand." + }, + { + "selector": "WithStatement", + "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize." + } + ], + "curly": [ + "error", + "all" + ] + }, + "globals": { + "BigInt": true + } +} diff --git a/node-grove/Cargo.toml b/node-grove/Cargo.toml index 8d0719ca3..21f99860f 100644 --- a/node-grove/Cargo.toml +++ b/node-grove/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "node-grove" -version = "0.1.0" +version = "0.2.0" description = "GroveDB node.js bindings" edition = "2021" license = "MIT" diff --git a/node-grove/README.md b/node-grove/README.md index 74a28a6a6..205a7485f 100644 --- a/node-grove/README.md +++ b/node-grove/README.md @@ -2,21 +2,21 @@ [![GroveDB npm package](https://img.shields.io/npm/v/@dashevo/node-grove.svg)](https://www.npmjs.com/package/@dashevo/node-grove) -`node-grove` is a GroveDB binding for node.js +`node-grove` is a GroveDB binding for Node.JS -`node-grove` is [available on npm](https://www.npmjs.com/package/@dashevo/node-grove) +`node-grove` is [available on npm](https://www.npmjs.com/package/@dashevo/grovedb) ## Usage -Add the module to your project with `npm install @dashevo/node-grove`. +Add the module to your project with `npm install @dashevo/grovedb`. ## Example ```javascript -const GroveDB = require('@dashevo/node-grove'); +const GroveDB = require('@dashevo/grovedb'); (async function main() { - const groveDb = GroveDB.open('./test.db'); + const groveDb = new GroveDB('./test.db'); const tree_key = Buffer.from("test_tree"); @@ -60,10 +60,10 @@ Run `npm run build` to build the package, `npm test` to test it. The main file that is used form the node.js side is `index.js`. It contains class named `GroveDb`. The actual functions this class makes calls to are -stored in the `./src/lib.rs`. When building the project, it is compiled to -a file called `index.node`, that is imported into the `index.js` file. +stored in the `./src/lib.rs`. When building the project, it is compiled to +binary in the `prebuilds` directory. This binary imported into the `index.js` file. -Please note that the binding itself contains a lot of code. This is due to +Please note that the binding itself contains a lot of code. This is due to the fact that GroveDB is not thread-safe, and needs to live in its own thread. It communicates with the main binding thread through messages. diff --git a/node-grove/index.js b/node-grove/index.js index 1f55db046..40ce0d328 100644 --- a/node-grove/index.js +++ b/node-grove/index.js @@ -1,66 +1,221 @@ -"use strict"; - -const { promisify } = require("util"); +const { promisify } = require('util'); // This file is crated when run `npm run build`. The actual source file that // exports those functions is ./src/lib.rs -const { groveDbOpen, groveDbGet, groveDbInsert, groveDbProof, groveDbClose } = require("../index.node"); +const { + groveDbOpen, + groveDbGet, + groveDbInsert, + groveDbClose, + groveDbFlush, + groveDbStartTransaction, + groveDbCommitTransaction, + groveDbRollbackTransaction, + groveDbIsTransactionStarted, + groveDbAbortTransaction, + groveDbDelete, + groveDbInsertIfNotExists, + groveDbPutAux, + groveDbDeleteAux, + groveDbGetAux, + groveDbGetPathQuery, + groveDbRootHash, +} = require('neon-load-or-build')({ + dir: __dirname, +}); // Convert the DB methods from using callbacks to returning promises const groveDbGetAsync = promisify(groveDbGet); const groveDbInsertAsync = promisify(groveDbInsert); -const groveDbProofAsync = promisify(groveDbProof); +const groveDbInsertIfNotExistsAsync = promisify(groveDbInsertIfNotExists); +const groveDbDeleteAsync = promisify(groveDbDelete); const groveDbCloseAsync = promisify(groveDbClose); +const groveDbFlushAsync = promisify(groveDbFlush); +const groveDbStartTransactionAsync = promisify(groveDbStartTransaction); +const groveDbCommitTransactionAsync = promisify(groveDbCommitTransaction); +const groveDbRollbackTransactionAsync = promisify(groveDbRollbackTransaction); +const groveDbIsTransactionStartedAsync = promisify(groveDbIsTransactionStarted); +const groveDbAbortTransactionAsync = promisify(groveDbAbortTransaction); +const groveDbPutAuxAsync = promisify(groveDbPutAux); +const groveDbDeleteAuxAsync = promisify(groveDbDeleteAux); +const groveDbGetAuxAsync = promisify(groveDbGetAux); +const groveDbGetPathQueryAsync = promisify(groveDbGetPathQuery); +const groveDbRootHashAsync = promisify(groveDbRootHash); // Wrapper class for the boxed `Database` for idiomatic JavaScript usage class GroveDB { - constructor(db) { - this.db = db; - } - - static open(path) { - const db = groveDbOpen(path); - return new GroveDB(db); - } - - /** - * - * @param {Buffer[]} path - * @param {Buffer} key - * @returns {Promise} - */ - async get(path, key) { - return groveDbGetAsync.call(this.db, path, key); - } - - /** - * - * @param {Buffer[]} path - * @param {Buffer} key - * @param {Element} value - * @returns {Promise<*>} - */ - async insert(path, key, value) { - return groveDbInsertAsync.call(this.db, path, key, value); - } - - /** - * Not implemented in GroveDB yet - * - * @returns {Promise<*>} - */ - async proof() { - return groveDbProofAsync.call(this.db); - } - - /** - * Closes connection to the DB - * - * @returns {Promise} - */ - async close() { - return groveDbCloseAsync.call(this.db); - } + /** + * @param {string} dbPath + */ + constructor(dbPath) { + this.db = groveDbOpen(dbPath); + } + + /** + * @param {Buffer[]} path + * @param {Buffer} key + * @param {boolean} [useTransaction=false] + * @returns {Promise} + */ + async get(path, key, useTransaction = false) { + return groveDbGetAsync.call(this.db, path, key, useTransaction); + } + + /** + * @param {Buffer[]} path + * @param {Buffer} key + * @param {Element} value + * @param {boolean} [useTransaction=false] + * @returns {Promise<*>} + */ + async insert(path, key, value, useTransaction = false) { + return groveDbInsertAsync.call(this.db, path, key, value, useTransaction); + } + + /** + * @param {Buffer[]} path + * @param {Buffer} key + * @param {Element} value + * @param {boolean} [useTransaction=false] + * @return {Promise<*>} + */ + async insertIfNotExists(path, key, value, useTransaction = false) { + return groveDbInsertIfNotExistsAsync.call(this.db, path, key, value, useTransaction); + } + + /** + * + * @param {Buffer[]} path + * @param {Buffer} key + * @param {boolean} [useTransaction=false] + * @return {Promise<*>} + */ + async delete(path, key, useTransaction = false) { + return groveDbDeleteAsync.call(this.db, path, key, useTransaction); + } + + /** + * Flush data on the disk + * + * @returns {Promise} + */ + async flush() { + return groveDbFlushAsync.call(this.db); + } + + /** + * Close connection to the DB + * + * @returns {Promise} + */ + async close() { + return groveDbCloseAsync.call(this.db); + } + + /** + * Start a transaction with isolated scope + * + * Write operations will be allowed only for the transaction + * until it's committed + * + * @return {Promise} + */ + async startTransaction() { + return groveDbStartTransactionAsync.call(this.db); + } + + /** + * Commit transaction + * + * Transaction should be started before + * + * @return {Promise} + */ + async commitTransaction() { + return groveDbCommitTransactionAsync.call(this.db); + } + + /** + * Rollback transaction to this initial state when it was created + * + * @returns {Promise} + */ + async rollbackTransaction() { + return groveDbRollbackTransactionAsync.call(this.db); + } + + /** + * Returns true if transaction started + * + * @returns {Promise} + */ + async isTransactionStarted() { + return groveDbIsTransactionStartedAsync.call(this.db); + } + + /** + * Aborts transaction + * + * @returns {Promise} + */ + async abortTransaction() { + return groveDbAbortTransactionAsync.call(this.db); + } + + /** + * Put auxiliary data + * + * @param {Buffer} key + * @param {Buffer} value + * @param {boolean} [useTransaction=false] + * @return {Promise<*>} + */ + async putAux(key, value, useTransaction = false) { + return groveDbPutAuxAsync.call(this.db, key, value, useTransaction); + } + + /** + * Delete auxiliary data + * + * @param {Buffer} key + * @param {boolean} [useTransaction=false] + * @return {Promise<*>} + */ + async deleteAux(key, useTransaction = false) { + return groveDbDeleteAuxAsync.call(this.db, key, useTransaction); + } + + /** + * Get auxiliary data + * + * @param {Buffer} key + * @param {boolean} [useTransaction=false] + * @return {Promise} + */ + async getAux(key, useTransaction = false) { + return groveDbGetAuxAsync.call(this.db, key, useTransaction); + } + + /** + * Get data using query. + * + * @param {PathQuery} + * @param {boolean} [useTransaction=false] + * @return {Promise<*>} + */ + async getPathQuery(query, useTransaction = false) { + return groveDbGetPathQueryAsync.call(this.db, query, useTransaction); + } + + /** + * Get root hash + * + * @param {boolean} [useTransaction=false] + * @returns {Promise} + */ + async getRootHash(useTransaction = false) { + return groveDbRootHashAsync.call(this.db, useTransaction); + } } /** @@ -69,4 +224,25 @@ class GroveDB { * @property {Buffer|Buffer[]} value - element value */ +/** + * @typedef PathQuery + * @property {Buffer[]} path + * @property {SizedQuery} query + */ + +/** + * @typedef SizedQuery + * @property {Query} query + * @property {Number|null} limit + * @property {Number|null} offset + */ + +/** + * @typedef Query + * @property {Array} items + * @property {Buffer|null} subqueryKey + * @property {Query|null} subquery + * @property {boolean| null} leftToRight + */ + module.exports = GroveDB; diff --git a/node-grove/index.spec.js b/node-grove/index.spec.js index fc160c7cf..e32a0d1a2 100644 --- a/node-grove/index.spec.js +++ b/node-grove/index.spec.js @@ -1,79 +1,1059 @@ -const GroveDB = require('./index.js'); -const rimraf = require('rimraf'); -const { promisify } = require("util"); -const removeTestDataFiles = promisify(rimraf); +const fs = require('fs'); + const { expect } = require('chai'); -const testDataPath = './test_data'; +const GroveDB = require('./index'); + +const TEST_DATA_PATH = './test_data'; describe('GroveDB', () => { - let groveDb; + let groveDb; + let treeKey; + let itemKey; + let itemValue; + let rootTreePath; + let itemTreePath; - beforeEach(() => { - groveDb = GroveDB.open(testDataPath); + beforeEach(() => { + groveDb = new GroveDB(TEST_DATA_PATH); + + treeKey = Buffer.from('test_tree'); + itemKey = Buffer.from('test_key'); + itemValue = Buffer.from('very nice test value'); + + rootTreePath = []; + itemTreePath = [treeKey]; + }); + + afterEach(async () => { + await groveDb.close(); + + fs.rmSync(TEST_DATA_PATH, { recursive: true }); + }); + + it('should store and retrieve a value', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + ); + + const element = await groveDb.get(itemTreePath, itemKey); + + expect(element.type).to.be.equal('item'); + expect(element.value).to.deep.equal(itemValue); + }); + + it('should store and delete a value', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + ); + + // Get item + const element = await groveDb.get(itemTreePath, itemKey); + + expect(element.type).to.be.equal('item'); + expect(element.value).to.deep.equal(itemValue); + + // Delete an item from the subtree + await groveDb.delete( + itemTreePath, + itemKey, + ); + + try { + await groveDb.get(itemTreePath, itemKey); + + expect.fail('Expected to throw en error'); + } catch (e) { + expect(e.message).to.be.equal('invalid path key: key not found in Merk: 746573745f6b6579'); + } + }); + + describe('#startTransaction', () => { + it('should not allow to insert data to main database after it called', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + await groveDb.startTransaction(); + + try { + // Inserting an item into the subtree without transaction + await groveDb.insert( + itemTreePath, + itemKey, + { + type: 'item', + value: itemValue, + }, + ); + + expect.fail('should throw an error'); + } catch (e) { + expect(e.message).to.equal('db is in readonly mode due to the active transaction. Please provide transaction or commit it'); + } }); - afterEach(async () => { - await groveDb.close(); - await removeTestDataFiles(testDataPath); + it('should not allow to read transactional data from main database until it\'s committed', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + await groveDb.startTransaction(); + + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + true, + ); + + // Inserted value is not yet commited, but can be retrieved by `get` + // with `useTransaction` flag. + const elementInTransaction = await groveDb.get(itemTreePath, itemKey, true); + + expect(elementInTransaction.type).to.be.equal('item'); + expect(elementInTransaction.value).to.deep.equal(itemValue); + + // ... and using `get` without the flag should return no value + try { + await groveDb.get(itemTreePath, itemKey); + + expect.fail('Expected to throw an error'); + } catch (e) { + expect(e.message).to.be.equal('invalid path key: key not found in Merk: 746573745f6b6579'); + } }); + }); - it('should store and retrieve a value', async function createGroveDb() { - const tree_key = Buffer.from("test_tree"); + describe('#commitTransaction', () => { + it('should commit transactional data to main database', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); - const item_key = Buffer.from("test_key"); - const item_value = Buffer.from("very nice test value"); + await groveDb.startTransaction(); - const root_tree_path = []; - const item_tree_path = [tree_key]; + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + true, + ); + + // ... and using `get` without the flag should return no value + try { + await groveDb.get(itemTreePath, itemKey); + + expect.fail('Expected to throw an error'); + } catch (e) { + expect(e.message).to.be.equal('invalid path key: key not found in Merk: 746573745f6b6579'); + } + + await groveDb.commitTransaction(); + + // When committed, the value should be accessible without running transaction + const element = await groveDb.get(itemTreePath, itemKey); + expect(element.type).to.be.equal('item'); + expect(element.value).to.deep.equal(itemValue); + }); + }); + + describe('#rollbackTransaction', () => { + it('should rollaback transaction state to its initial state', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + await groveDb.startTransaction(); + + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + true, + ); + + // Should rollback inserted item + await groveDb.rollbackTransaction(); + + try { + await groveDb.get(itemTreePath, itemKey); + + expect.fail('Expected to throw an error'); + } catch (e) { + expect(e.message).to.be.equal('invalid path key: key not found in Merk: 746573745f6b6579'); + } + }); + }); + + describe('#isTransactionStarted', () => { + it('should return true if transaction is started', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + await groveDb.startTransaction(); + + const result = await groveDb.isTransactionStarted(); + + // eslint-disable-next-line no-unused-expressions + expect(result).to.be.true; + }); + + it('should return false if transaction is not started', async () => { + const result = await groveDb.isTransactionStarted(); + + // eslint-disable-next-line no-unused-expressions + expect(result).to.be.false; + }); + }); + + describe('#abortTransaction', () => { + it('should abort transaction', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + await groveDb.startTransaction(); + + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + true, + ); + + // Should abort inserted item + await groveDb.abortTransaction(); + + const isTransactionStarted = await groveDb.isTransactionStarted(); + + // eslint-disable-next-line no-unused-expressions + expect(isTransactionStarted).to.be.false; + + try { + await groveDb.get(itemTreePath, itemKey); + + expect.fail('Expected to throw an error'); + } catch (e) { + expect(e.message).to.be.equal('invalid path key: key not found in Merk: 746573745f6b6579'); + } + }); + }); - // Making a subtree to insert items into + describe('#insertIfNotExists', () => { + it('should insert a value if key is not exist yet', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + // Inserting an item into the subtree + await groveDb.insertIfNotExists( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + ); + + const element = await groveDb.get(itemTreePath, itemKey); + + expect(element.type).to.equal('item'); + expect(element.value).to.deep.equal(itemValue); + }); + + it('shouldn\'t overwrite already stored value', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + ); + + const newItemValue = Buffer.from('replaced item value'); + + // Inserting an item into the subtree + await groveDb.insertIfNotExists( + itemTreePath, + itemKey, + { type: 'item', value: newItemValue }, + ); + + const element = await groveDb.get(itemTreePath, itemKey); + + expect(element.type).to.equal('item'); + expect(element.value).to.deep.equal(itemValue); + }); + }); + + describe('#insert', () => { + it('should be able to insert a tree', async () => { + await groveDb.insert( + [], + Buffer.from('test_tree'), + { type: 'tree', value: Buffer.alloc(32) }, + ); + }); + + it('should throw when trying to insert non-existent element type', async () => { + const path = []; + const key = Buffer.from('test_key'); + + try { await groveDb.insert( - root_tree_path, - tree_key, - { type: "tree", value: Buffer.alloc(32) - }); + path, + key, + { type: 'not_a_tree', value: Buffer.alloc(32) }, + ); + + expect.fail('Expected to throw en error'); + } catch (e) { + expect(e.message).to.be.equal('Unexpected element type not_a_tree'); + } + }); + + it('should throw when trying to insert a tree that is not 32 bytes', async () => { + const path = []; + const key = Buffer.from('test_key'); - // Inserting an item into the subtree + try { await groveDb.insert( - item_tree_path, - item_key, - { type: "item", value: item_value } + path, + key, + { type: 'tree', value: Buffer.alloc(1) }, ); - const element = await groveDb.get(item_tree_path, item_key); - - expect(element.type).to.be.equal("item"); - expect(element.value.toString()).to.be.equal("very nice test value"); - }); - - describe('#insert', () => { - it('should be able to insert a tree', async () => { - await groveDb.insert([], Buffer.from("test_tree"), { type: "tree", value: Buffer.alloc(32) }) - }); - - it('should throw when trying to insert non-existent element type', async () => { - const path = []; - const key = Buffer.from("test_key"); - - try { - await groveDb.insert(path, key, { type: "not_a_tree", value: Buffer.alloc(32) }) - expect.fail("Expected to throw en error"); - } catch (e) { - expect(e.message).to.be.equal("Unexpected element type not_a_tree"); - } - }); - - it('should throw when trying to insert a tree that is not 32 bytes', async () => { - const path = []; - const key = Buffer.from("test_key"); - - try { - await groveDb.insert(path, key, { type: "tree", value: Buffer.alloc(1) }) - expect.fail("Expected to throw en error"); - } catch (e) { - expect(e.message).to.be.equal("Tree buffer is expected to be 32 bytes long, but got 1"); - } - }); - }) + expect.fail('Expected to throw en error'); + } catch (e) { + expect(e.message).to.be.equal('Tree buffer is expected to be 32 bytes long, but got 1'); + } + }); + }); + + describe('auxiliary data methods', () => { + let key; + let value; + + beforeEach(() => { + key = Buffer.from('aux_key'); + value = Buffer.from('ayy'); + }); + + it('should be able to store and get aux data', async () => { + await groveDb.putAux(key, value); + + const result = await groveDb.getAux(key); + + expect(result).to.deep.equal(value); + }); + + it('should be able to insert and delete aux data', async () => { + await groveDb.putAux(key, value); + + await groveDb.deleteAux(key); + + const result = await groveDb.getAux(key); + + // eslint-disable-next-line no-unused-expressions + expect(result).to.be.null; + }); + }); + + describe('#getPathQuery for Item subtrees', () => { + let aValue; + let aKey; + let bValue; + let bKey; + let cValue; + let cKey; + // let dPath; + // let dKey; + // let ePath; + + // let daValue; + // let dbValue; + // let dcValue; + // let eaValue; + // let eaKey; + // let ebValue; + + beforeEach(async () => { + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + aValue = Buffer.from('a'); + aKey = Buffer.from('aKey'); + bValue = Buffer.from('b'); + bKey = Buffer.from('bKey'); + cValue = Buffer.from('c'); + cKey = Buffer.from('cKey'); + // dKey = Buffer.from('dKey'); + // daValue = Buffer.from('da'); + // dbValue = Buffer.from('db'); + // dcValue = Buffer.from('dc'); + // eaValue = Buffer.from('ea'); + // eaKey = Buffer.from('eaKey'); + // ebValue = Buffer.from('eb'); + + await groveDb.insert( + itemTreePath, + aKey, + { type: 'item', value: aValue }, + ); + + await groveDb.insert( + itemTreePath, + bKey, + { type: 'item', value: bValue }, + ); + + await groveDb.insert( + itemTreePath, + cKey, + { type: 'item', value: cValue }, + ); + + // dPath = [...itemTreePath]; + // dPath.push(dKey); + // await groveDb.insert( + // itemTreePath, + // dKey, + // { type: 'tree', value: Buffer.alloc(32) }, + // ); + + // await groveDb.insert( + // dPath, + // Buffer.from('daKey'), + // { type: 'item', value: daValue }, + // ); + + // await groveDb.insert( + // dPath, + // Buffer.from('dbKey'), + // { type: 'item', value: dbValue }, + // ); + + // await groveDb.insert( + // dPath, + // Buffer.from('dcKey'), + // { type: 'item', value: dcValue }, + // ); + + // const eKey = Buffer.from('eKey'); + // ePath = [...itemTreePath]; + // ePath.push(eKey); + // await groveDb.insert( + // itemTreePath, + // eKey, + // { type: 'tree', value: Buffer.alloc(32) }, + // ); + + // await groveDb.insert( + // ePath, + // Buffer.from('eaKey'), + // { type: 'item', value: eaValue }, + // ); + + // await groveDb.insert( + // ePath, + // Buffer.from('ebKey'), + // { type: 'item', value: ebValue }, + // ); + }); + + it('should be able to use limit', async () => { + const query = { + path: itemTreePath, + query: { + limit: 1, + query: { + items: [ + { + type: 'rangeFrom', + from: bValue, + }, + ], + }, + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + bValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to use offset', async () => { + const query = { + path: itemTreePath, + query: { + offset: 1, + query: { + items: [ + { + type: 'rangeFrom', + from: bValue, + }, + ], + }, + + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + cValue, + ]); + + expect(skipped).to.equals(1); + }); + + it('should be able to retrieve data using `key`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'key', + key: aKey, + }, + { + type: 'key', + key: bKey, + }, + ], + }, + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + aValue, + bValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `range`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'range', + from: aKey, + to: cKey, + }, + ], + }, + + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + aValue, + bValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `rangeInclusive`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeInclusive', + from: aKey, + to: bKey, + }, + ], + }, + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + aValue, + bValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `rangeFull`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeFull', + }, + ], + }, + + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + aValue, + bValue, + cValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `rangeFrom`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeFrom', + from: bKey, + }, + ], + }, + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + bValue, + cValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `rangeTo`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeTo', + to: cKey, + }, + ], + }, + + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + aValue, + bValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `rangeToInclusive`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeToInclusive', + to: cKey, + }, + ], + }, + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + aValue, + bValue, + cValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `rangeAfter`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeAfter', + after: aKey, + }, + ], + }, + + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + bValue, + cValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `rangeAfterTo`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeAfterTo', + after: aKey, + to: cKey, + }, + ], + }, + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + bValue, + ]); + + expect(skipped).to.equals(0); + }); + + it('should be able to retrieve data using `rangeAfterToInclusive`', async () => { + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeAfterToInclusive', + after: aKey, + to: cKey, + }, + ], + }, + + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + bValue, + cValue, + ]); + + expect(skipped).to.equals(0); + }); + }); + + describe('#getPathQuery for nested subtrees with subquery', () => { + let dPath; + let dKey; + let ePath; + + let daValue; + let dbValue; + let dcValue; + let eaValue; + let eaKey; + let ebValue; + + beforeEach(async () => { + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + dKey = Buffer.from('dKey'); + daValue = Buffer.from('da'); + dbValue = Buffer.from('db'); + dcValue = Buffer.from('dc'); + eaValue = Buffer.from('ea'); + eaKey = Buffer.from('eaKey'); + ebValue = Buffer.from('eb'); + + dPath = [...itemTreePath]; + dPath.push(dKey); + await groveDb.insert( + itemTreePath, + dKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + await groveDb.insert( + dPath, + Buffer.from('daKey'), + { type: 'item', value: daValue }, + ); + + await groveDb.insert( + dPath, + Buffer.from('dbKey'), + { type: 'item', value: dbValue }, + ); + + await groveDb.insert( + dPath, + Buffer.from('dcKey'), + { type: 'item', value: dcValue }, + ); + + const eKey = Buffer.from('eKey'); + ePath = [...itemTreePath]; + ePath.push(eKey); + await groveDb.insert( + itemTreePath, + eKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + await groveDb.insert( + ePath, + Buffer.from('eaKey'), + { type: 'item', value: eaValue }, + ); + + await groveDb.insert( + ePath, + Buffer.from('ebKey'), + { type: 'item', value: ebValue }, + ); + }); + + it('should be able to retrieve data with subquery', async () => { + // This should give us only last subtree and apply subquery to it + const query = { + path: itemTreePath, + query: { + query: { + items: [ + { + type: 'rangeAfter', + after: dKey, + }, + ], + subquery: { + items: [ + { + type: 'rangeAfter', + after: eaKey, + }, + ], + }, + }, + }, + }; + + const result = await groveDb.getPathQuery(query); + + expect(result).to.have.a.lengthOf(2); + + const [elementValues, skipped] = result; + + expect(elementValues).to.deep.equals([ + ebValue, + ]); + + expect(skipped).to.equals(0); + }); + }); + + describe('#flush', () => { + it('should flush data on disc', async () => { + await groveDb.insert( + [], + Buffer.from('test_tree'), + { type: 'tree', value: Buffer.alloc(32) }, + ); + + await groveDb.flush(); + }); + }); + + describe('#getRootHash', () => { + it('should return empty root hash if there is no data', async () => { + const result = await groveDb.getRootHash(); + + expect(result).to.deep.equal(Buffer.alloc(32)); + + // Get root hash for transaction too + await groveDb.startTransaction(); + + const transactionalResult = await groveDb.getRootHash(true); + + expect(transactionalResult).to.deep.equal(Buffer.alloc(32)); + }); + }); + + it('should root hash', async () => { + // Making a subtree to insert items into + await groveDb.insert( + rootTreePath, + treeKey, + { type: 'tree', value: Buffer.alloc(32) }, + ); + + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + itemKey, + { type: 'item', value: itemValue }, + ); + + await groveDb.startTransaction(); + + // Inserting an item into the subtree + await groveDb.insert( + itemTreePath, + Buffer.from('transactional_test_key'), + { type: 'item', value: itemValue }, + true, + ); + + const result = await groveDb.getRootHash(); + const transactionalResult = await groveDb.getRootHash(true); + + // Hashes shouldn't be equal + expect(result).to.not.deep.equal(transactionalResult); + + // Hashes shouldn't be empty + + // eslint-disable-next-line no-unused-expressions + expect(result >= Buffer.alloc(32)).to.be.true; + + // eslint-disable-next-line no-unused-expressions + expect(transactionalResult >= Buffer.alloc(32)).to.be.true; + }); }); diff --git a/node-grove/src/converter.rs b/node-grove/src/converter.rs index 60eba685d..6463492f2 100644 --- a/node-grove/src/converter.rs +++ b/node-grove/src/converter.rs @@ -1,4 +1,4 @@ -use grovedb::Element; +use grovedb::{Element, PathQuery, Query, SizedQuery}; use neon::{borrow::Borrow, prelude::*}; fn element_to_string(element: Element) -> String { @@ -58,17 +58,7 @@ pub fn element_to_js_object<'a, C: Context<'a>>( let js_buffer = JsBuffer::external(cx, item); js_buffer.upcast() } - Element::Reference(reference) => { - let js_array: Handle = cx.empty_array(); - - for (index, bytes) in reference.iter().enumerate() { - let js_buffer = JsBuffer::external(cx, bytes.clone()); - let js_value = js_buffer.as_value(cx); - js_array.set(cx, index as u32, js_value)?; - } - - js_array.upcast() - } + Element::Reference(reference) => nested_vecs_to_js(reference, cx)?, Element::Tree(tree) => { let js_buffer = JsBuffer::external(cx, tree); js_buffer.upcast() @@ -79,6 +69,21 @@ pub fn element_to_js_object<'a, C: Context<'a>>( NeonResult::Ok(js_object.upcast()) } +pub fn nested_vecs_to_js<'a, C: Context<'a>>( + v: Vec>, + cx: &mut C, +) -> NeonResult> { + let js_array: Handle = cx.empty_array(); + + for (index, bytes) in v.iter().enumerate() { + let js_buffer = JsBuffer::external(cx, bytes.clone()); + let js_value = js_buffer.as_value(cx); + js_array.set(cx, index as u32, js_value)?; + } + + Ok(js_array.upcast()) +} + pub fn js_buffer_to_vec_u8<'a, C: Context<'a>>(js_buffer: Handle, cx: &mut C) -> Vec { let guard = cx.lock(); // let key_buffer = js_buffer.deref(); @@ -101,3 +106,138 @@ pub fn js_array_of_buffers_to_vec<'a, C: Context<'a>>( Ok(vec) } + +pub fn js_value_to_option<'a, T: Value, C: Context<'a>>( + js_value: Handle<'a, JsValue>, + cx: &mut C, +) -> NeonResult>> { + if js_value.is_a::(cx) || js_value.is_a::(cx) { + Ok(None) + } else { + Ok(Some(js_value.downcast_or_throw::(cx)?)) + } +} + +fn js_object_get_vec_u8<'a, C: Context<'a>>( + js_object: Handle, + field: &str, + cx: &mut C, +) -> NeonResult> { + Ok(js_buffer_to_vec_u8( + js_object + .get(cx, field)? + .downcast_or_throw::(cx)?, + cx, + )) +} + +fn js_object_to_query<'a, C: Context<'a>>( + js_object: Handle, + cx: &mut C, +) -> NeonResult { + let items = js_object + .get(cx, "items")? + .downcast_or_throw::(cx)?; + let mut query = Query::new(); + for js_item in items.to_vec(cx)? { + let item = js_item.downcast_or_throw::(cx)?; + match item + .get(cx, "type")? + .downcast_or_throw::(cx)? + .value(cx) + .as_ref() + { + "key" => { + query.insert_key(js_object_get_vec_u8(item, "key", cx)?); + } + "range" => { + let from = js_object_get_vec_u8(item, "from", cx)?; + let to = js_object_get_vec_u8(item, "to", cx)?; + query.insert_range(from..to); + } + "rangeInclusive" => { + let from = js_object_get_vec_u8(item, "from", cx)?; + let to = js_object_get_vec_u8(item, "to", cx)?; + query.insert_range_inclusive(from..=to); + } + "rangeFull" => { + query.insert_all(); + } + "rangeFrom" => { + query.insert_range_from(js_object_get_vec_u8(item, "from", cx)?..); + } + "rangeTo" => { + query.insert_range_to(..js_object_get_vec_u8(item, "to", cx)?); + } + "rangeToInclusive" => { + query.insert_range_to_inclusive(..=js_object_get_vec_u8(item, "to", cx)?); + } + "rangeAfter" => { + query.insert_range_after(js_object_get_vec_u8(item, "after", cx)?..); + } + "rangeAfterTo" => { + let after = js_object_get_vec_u8(item, "after", cx)?; + let to = js_object_get_vec_u8(item, "to", cx)?; + query.insert_range_after_to(after..to); + } + "rangeAfterToInclusive" => { + let after = js_object_get_vec_u8(item, "after", cx)?; + let to = js_object_get_vec_u8(item, "to", cx)?; + query.insert_range_after_to_inclusive(after..=to); + } + _ => { + cx.throw_range_error("query item type is not supported")?; + } + } + } + + let subquery_key = js_value_to_option::(js_object.get(cx, "subqueryKey")?, cx)? + .map(|x| js_buffer_to_vec_u8(x, cx)); + let subquery = js_value_to_option::(js_object.get(cx, "subquery")?, cx)? + .map(|x| js_object_to_query(x, cx)) + .transpose()?; + let left_to_right = js_value_to_option::(js_object.get(cx, "leftToRight")?, cx)? + .map(|x| x.value(cx)); + + query.subquery_key = subquery_key; + query.subquery = subquery.map(Box::new); + query.left_to_right = left_to_right.unwrap_or(true); + + Ok(query) +} + +fn js_object_to_sized_query<'a, C: Context<'a>>( + js_object: Handle, + cx: &mut C, +) -> NeonResult { + let query = js_object_to_query( + js_object + .get(cx, "query")? + .downcast_or_throw::(cx)?, + cx, + )?; + let limit: Option = js_value_to_option::(js_object.get(cx, "limit")?, cx)? + .map(|x| { + u16::try_from(x.value(cx) as i64) + .or_else(|_| cx.throw_range_error("`limit` must fit in u16")) + }) + .transpose()?; + let offset: Option = js_value_to_option::(js_object.get(cx, "offset")?, cx)? + .map(|x| { + u16::try_from(x.value(cx) as i64) + .or_else(|_| cx.throw_range_error("`offset` must fit in u16")) + }) + .transpose()?; + Ok(SizedQuery::new(query, limit, offset)) +} + +pub fn js_path_query_to_path_query<'a, C: Context<'a>>( + js_path_query: Handle, + cx: &mut C, +) -> NeonResult { + let path = + js_array_of_buffers_to_vec(js_path_query.get(cx, "path")?.downcast_or_throw(cx)?, cx)?; + let query = + js_object_to_sized_query(js_path_query.get(cx, "query")?.downcast_or_throw(cx)?, cx)?; + Ok(PathQuery::new(path, query)) +} diff --git a/node-grove/src/lib.rs b/node-grove/src/lib.rs index 007256b15..6a52ec73d 100644 --- a/node-grove/src/lib.rs +++ b/node-grove/src/lib.rs @@ -2,18 +2,29 @@ mod converter; use std::{option::Option::None, path::Path, sync::mpsc, thread}; -use grovedb::GroveDb; +use grovedb::{GroveDb, PrefixedRocksDbStorage, Storage}; use neon::prelude::*; -type DbCallback = Box; -type CloseCallback = Box; +type DbCallback = Box< + dyn for<'a> FnOnce( + &'a mut GroveDb, + Option<&::DBTransaction<'a>>, + &Channel, + ) + Send, +>; +type UnitCallback = Box; // Messages sent on the database channel enum DbMessage { // Callback to be executed Callback(DbCallback), // Indicates that the thread should be stopped and connection closed - Close(CloseCallback), + Close(UnitCallback), + StartTransaction(UnitCallback), + CommitTransaction(UnitCallback), + RollbackTransaction(UnitCallback), + AbortTransaction(UnitCallback), + Flush(UnitCallback), } struct GroveDbWrapper { @@ -50,6 +61,10 @@ impl GroveDbWrapper { // Open a connection to groveDb, this will be moved to a separate thread // TODO: think how to pass this error to JS let mut grove_db = GroveDb::open(path).unwrap(); + let storage = grove_db.storage(); + + let mut transaction: Option<::DBTransaction<'_>> = + None; // Blocks until a callback is available // When the instance of `Database` is dropped, the channel will be closed @@ -61,13 +76,45 @@ impl GroveDbWrapper { // The connection and channel are owned by the thread, but _lent_ to // the callback. The callback has exclusive access to the connection // for the duration of the callback. - callback(&mut grove_db, &channel); + callback(&mut grove_db, transaction.as_ref(), &channel); } // Immediately close the connection, even if there are pending messages DbMessage::Close(callback) => { + drop(transaction); + drop(storage); + drop(grove_db); callback(&channel); break; } + // Flush message + DbMessage::Flush(callback) => { + grove_db.flush().unwrap(); + + callback(&channel); + } + DbMessage::StartTransaction(callback) => { + grove_db.start_transaction().unwrap(); + transaction = Some(storage.transaction()); + callback(&channel); + } + DbMessage::CommitTransaction(callback) => { + grove_db + .commit_transaction(transaction.take().unwrap()) + .unwrap(); + callback(&channel); + } + DbMessage::RollbackTransaction(callback) => { + grove_db + .rollback_transaction(&transaction.take().unwrap()) + .unwrap(); + callback(&channel); + } + DbMessage::AbortTransaction(callback) => { + grove_db + .abort_transaction(transaction.take().unwrap()) + .unwrap(); + callback(&channel); + } } } }); @@ -85,12 +132,59 @@ impl GroveDbWrapper { self.tx.send(DbMessage::Close(Box::new(callback))) } + // Idiomatic rust would take an owned `self` to prevent use after close + // However, it's not possible to prevent JavaScript from continuing to hold a + // closed database + fn flush( + &self, + callback: impl FnOnce(&Channel) + Send + 'static, + ) -> Result<(), mpsc::SendError> { + self.tx.send(DbMessage::Flush(Box::new(callback))) + } + fn send_to_db_thread( &self, - callback: impl FnOnce(&mut GroveDb, &Channel) + Send + 'static, + callback: impl for<'a> FnOnce( + &'a mut GroveDb, + Option<&::DBTransaction<'a>>, + &Channel, + ) + Send + + 'static, ) -> Result<(), mpsc::SendError> { self.tx.send(DbMessage::Callback(Box::new(callback))) } + + fn start_transaction( + &self, + callback: impl FnOnce(&Channel) + Send + 'static, + ) -> Result<(), mpsc::SendError> { + self.tx + .send(DbMessage::StartTransaction(Box::new(callback))) + } + + fn commit_transaction( + &self, + callback: impl FnOnce(&Channel) + Send + 'static, + ) -> Result<(), mpsc::SendError> { + self.tx + .send(DbMessage::CommitTransaction(Box::new(callback))) + } + + fn rollback_transaction( + &self, + callback: impl FnOnce(&Channel) + Send + 'static, + ) -> Result<(), mpsc::SendError> { + self.tx + .send(DbMessage::RollbackTransaction(Box::new(callback))) + } + + fn abort_transaction( + &self, + callback: impl FnOnce(&Channel) + Send + 'static, + ) -> Result<(), mpsc::SendError> { + self.tx + .send(DbMessage::AbortTransaction(Box::new(callback))) + } } // Ensures that GroveDbWrapper is properly disposed when the corresponding JS @@ -108,10 +202,133 @@ impl GroveDbWrapper { Ok(cx.boxed(grove_db_wrapper)) } + fn js_start_transaction(mut cx: FunctionContext) -> JsResult { + let js_callback = cx.argument::(0)?.root(&mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + + db.start_transaction(|channel| { + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = vec![task_context.null().upcast()]; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + Ok(cx.undefined()) + } + + fn js_commit_transaction(mut cx: FunctionContext) -> JsResult { + let js_callback = cx.argument::(0)?.root(&mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + + db.commit_transaction(|channel| { + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = vec![task_context.null().upcast()]; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + Ok(cx.undefined()) + } + + fn js_rollback_transaction(mut cx: FunctionContext) -> JsResult { + let js_callback = cx.argument::(0)?.root(&mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + + db.rollback_transaction(|channel| { + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = vec![task_context.null().upcast()]; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + Ok(cx.undefined()) + } + + fn js_is_transaction_started(mut cx: FunctionContext) -> JsResult { + let js_callback = cx.argument::(0)?.root(&mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + + db.send_to_db_thread(move |grove_db: &mut GroveDb, _transaction, channel| { + let result = grove_db.is_transaction_started(); + + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + + // First parameter of JS callbacks is error, which is null in this case + let callback_arguments: Vec> = vec![ + task_context.null().upcast(), + task_context.boolean(result).upcast(), + ]; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + Ok(cx.undefined()) + } + + fn js_abort_transaction(mut cx: FunctionContext) -> JsResult { + let js_callback = cx.argument::(0)?.root(&mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + + db.abort_transaction(|channel| { + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = vec![task_context.null().upcast()]; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + Ok(cx.undefined()) + } + fn js_get(mut cx: FunctionContext) -> JsResult { let js_path = cx.argument::(0)?; let js_key = cx.argument::(1)?; - let js_callback = cx.argument::(2)?.root(&mut cx); + let js_using_transaction = cx.argument::(2)?; + let js_callback = cx.argument::(3)?.root(&mut cx); let path = converter::js_array_of_buffers_to_vec(js_path, &mut cx)?; let key = converter::js_buffer_to_vec_u8(js_key, &mut cx); @@ -120,10 +337,15 @@ impl GroveDbWrapper { let db = cx .this() .downcast_or_throw::, _>(&mut cx)?; + let using_transaction = js_using_transaction.value(&mut cx); - db.send_to_db_thread(move |grove_db: &mut GroveDb, channel| { + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { let path_slice: Vec<&[u8]> = path.iter().map(|fragment| fragment.as_slice()).collect(); - let result = grove_db.get(&path_slice, &key, None); + let result = grove_db.get( + &path_slice, + &key, + using_transaction.then(|| transaction).flatten(), + ); channel.send(move |mut task_context| { let callback = js_callback.into_inner(&mut task_context); @@ -152,25 +374,76 @@ impl GroveDbWrapper { Ok(cx.undefined()) } + fn js_delete(mut cx: FunctionContext) -> JsResult { + let js_path = cx.argument::(0)?; + let js_key = cx.argument::(1)?; + let js_using_transaction = cx.argument::(2)?; + let js_callback = cx.argument::(3)?.root(&mut cx); + + let path = converter::js_array_of_buffers_to_vec(js_path, &mut cx)?; + let key = converter::js_buffer_to_vec_u8(js_key, &mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + let using_transaction = js_using_transaction.value(&mut cx); + + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { + let path_slice: Vec<&[u8]> = path.iter().map(|fragment| fragment.as_slice()).collect(); + let result = grove_db.delete( + &path_slice, + key, + using_transaction.then(|| transaction).flatten(), + ); + + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = match result { + Ok(()) => { + vec![task_context.null().upcast()] + } + + // Convert the error to a JavaScript exception on failure + Err(err) => vec![task_context.error(err.to_string())?.upcast()], + }; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + // The result is returned through the callback, not through direct return + Ok(cx.undefined()) + } + fn js_insert(mut cx: FunctionContext) -> JsResult { let js_path = cx.argument::(0)?; let js_key = cx.argument::(1)?; let js_element = cx.argument::(2)?; - let js_callback = cx.argument::(3)?.root(&mut cx); + let js_using_transaction = cx.argument::(3)?; + let js_callback = cx.argument::(4)?.root(&mut cx); let path = converter::js_array_of_buffers_to_vec(js_path, &mut cx)?; let key = converter::js_buffer_to_vec_u8(js_key, &mut cx); let element = converter::js_object_to_element(js_element, &mut cx)?; + let using_transaction = js_using_transaction.value(&mut cx); // Get the `this` value as a `JsBox` let db = cx .this() .downcast_or_throw::, _>(&mut cx)?; - db.send_to_db_thread(move |grove_db: &mut GroveDb, channel| { + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { let path_slice: Vec<&[u8]> = path.iter().map(|fragment| fragment.as_slice()).collect(); - // TODO: IMPLEMENT BINDINGS FOR THE TRANSACTION - let result = grove_db.insert(&path_slice, key, element, None); + let result = grove_db.insert( + &path_slice, + key, + element, + using_transaction.then(|| transaction).flatten(), + ); channel.send(move |mut task_context| { let callback = js_callback.into_inner(&mut task_context); @@ -189,6 +462,228 @@ impl GroveDbWrapper { Ok(cx.undefined()) } + fn js_insert_if_not_exists(mut cx: FunctionContext) -> JsResult { + let js_path = cx.argument::(0)?; + let js_key = cx.argument::(1)?; + let js_element = cx.argument::(2)?; + let js_using_transaction = cx.argument::(3)?; + let js_callback = cx.argument::(4)?.root(&mut cx); + + let path = converter::js_array_of_buffers_to_vec(js_path, &mut cx)?; + let key = converter::js_buffer_to_vec_u8(js_key, &mut cx); + let element = converter::js_object_to_element(js_element, &mut cx)?; + let using_transaction = js_using_transaction.value(&mut cx); + + // Get the `this` value as a `JsBox` + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { + let path_slice: Vec<&[u8]> = path.iter().map(|fragment| fragment.as_slice()).collect(); + let result = grove_db.insert_if_not_exists( + &path_slice, + key, + element, + using_transaction.then(|| transaction).flatten(), + ); + + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = match result { + Ok(is_inserted) => vec![ + task_context.null().upcast(), + task_context + .boolean(is_inserted) + .as_value(&mut task_context), + ], + Err(err) => vec![task_context.error(err.to_string())?.upcast()], + }; + + callback.call(&mut task_context, this, callback_arguments)?; + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + Ok(cx.undefined()) + } + + fn js_put_aux(mut cx: FunctionContext) -> JsResult { + let js_key = cx.argument::(0)?; + let js_value = cx.argument::(1)?; + let js_using_transaction = cx.argument::(2)?; + let js_callback = cx.argument::(3)?.root(&mut cx); + + let key = converter::js_buffer_to_vec_u8(js_key, &mut cx); + let value = converter::js_buffer_to_vec_u8(js_value, &mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + let using_transaction = js_using_transaction.value(&mut cx); + + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { + let result = grove_db.put_aux( + &key, + &value, + using_transaction.then(|| transaction).flatten(), + ); + + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = match result { + Ok(()) => { + vec![task_context.null().upcast()] + } + + // Convert the error to a JavaScript exception on failure + Err(err) => vec![task_context.error(err.to_string())?.upcast()], + }; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + // The result is returned through the callback, not through direct return + Ok(cx.undefined()) + } + + fn js_delete_aux(mut cx: FunctionContext) -> JsResult { + let js_key = cx.argument::(0)?; + let js_using_transaction = cx.argument::(1)?; + let js_callback = cx.argument::(2)?.root(&mut cx); + + let key = converter::js_buffer_to_vec_u8(js_key, &mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + let using_transaction = js_using_transaction.value(&mut cx); + + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { + let result = + grove_db.delete_aux(&key, using_transaction.then(|| transaction).flatten()); + + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = match result { + Ok(()) => { + vec![task_context.null().upcast()] + } + + // Convert the error to a JavaScript exception on failure + Err(err) => vec![task_context.error(err.to_string())?.upcast()], + }; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + // The result is returned through the callback, not through direct return + Ok(cx.undefined()) + } + + fn js_get_aux(mut cx: FunctionContext) -> JsResult { + let js_key = cx.argument::(0)?; + let js_using_transaction = cx.argument::(1)?; + let js_callback = cx.argument::(2)?.root(&mut cx); + + let key = converter::js_buffer_to_vec_u8(js_key, &mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + let using_transaction = js_using_transaction.value(&mut cx); + + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { + let result = grove_db.get_aux(&key, using_transaction.then(|| transaction).flatten()); + + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = match result { + Ok(value) => { + if let Some(value) = value { + vec![ + task_context.null().upcast(), + JsBuffer::external(&mut task_context, value).upcast(), + ] + } else { + vec![task_context.null().upcast(), task_context.null().upcast()] + } + } + + // Convert the error to a JavaScript exception on failure + Err(err) => vec![task_context.error(err.to_string())?.upcast()], + }; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + // The result is returned through the callback, not through direct return + Ok(cx.undefined()) + } + + fn js_get_path_query(mut cx: FunctionContext) -> JsResult { + let js_path_query = cx.argument::(0)?; + let js_using_transaction = cx.argument::(1)?; + let js_callback = cx.argument::(2)?.root(&mut cx); + + let path_query = converter::js_path_query_to_path_query(js_path_query, &mut cx)?; + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + let using_transaction = js_using_transaction.value(&mut cx); + + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { + let result = grove_db.get_path_query( + &path_query, + using_transaction.then(|| transaction).flatten(), + ); + + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = match result { + Ok((value, skipped)) => { + let js_array: Handle = task_context.empty_array(); + let js_vecs = converter::nested_vecs_to_js(value, &mut task_context)?; + let js_num = task_context.number(skipped).upcast::(); + js_array.set(&mut task_context, 0, js_vecs)?; + js_array.set(&mut task_context, 1, js_num)?; + vec![task_context.null().upcast(), js_array.upcast()] + } + + // Convert the error to a JavaScript exception on failure + Err(err) => vec![task_context.error(err.to_string())?.upcast()], + }; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + // The result is returned through the callback, not through direct return + Ok(cx.undefined()) + } + /// Not implemented fn js_proof(mut cx: FunctionContext) -> JsResult { Ok(cx.undefined()) @@ -219,15 +714,108 @@ impl GroveDbWrapper { Ok(cx.undefined()) } + + /// Flush data on disc and then calls js callback passed as a first + /// argument to the function + fn js_flush(mut cx: FunctionContext) -> JsResult { + let js_callback = cx.argument::(0)?.root(&mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + + db.flush(|channel| { + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + let callback_arguments: Vec> = vec![task_context.null().upcast()]; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + Ok(cx.undefined()) + } + + /// Returns root hash or empty buffer + fn js_root_hash(mut cx: FunctionContext) -> JsResult { + let js_using_transaction = cx.argument::(0)?; + let js_callback = cx.argument::(1)?.root(&mut cx); + + let db = cx + .this() + .downcast_or_throw::, _>(&mut cx)?; + + let using_transaction = js_using_transaction.value(&mut cx); + + db.send_to_db_thread(move |grove_db: &mut GroveDb, transaction, channel| { + let result = grove_db.root_hash(using_transaction.then(|| transaction).flatten()); + + channel.send(move |mut task_context| { + let callback = js_callback.into_inner(&mut task_context); + let this = task_context.undefined(); + + let hash = match result { + Some(hash) => JsBuffer::external(&mut task_context, hash), + None => task_context.buffer(32)?, + }; + + let callback_arguments: Vec> = + vec![task_context.null().upcast(), hash.upcast()]; + + callback.call(&mut task_context, this, callback_arguments)?; + + Ok(()) + }); + }) + .or_else(|err| cx.throw_error(err.to_string()))?; + + // The result is returned through the callback, not through direct return + Ok(cx.undefined()) + } } #[neon::main] fn main(mut cx: ModuleContext) -> NeonResult<()> { cx.export_function("groveDbOpen", GroveDbWrapper::js_open)?; cx.export_function("groveDbInsert", GroveDbWrapper::js_insert)?; + cx.export_function( + "groveDbInsertIfNotExists", + GroveDbWrapper::js_insert_if_not_exists, + )?; cx.export_function("groveDbGet", GroveDbWrapper::js_get)?; + cx.export_function("groveDbDelete", GroveDbWrapper::js_delete)?; cx.export_function("groveDbProof", GroveDbWrapper::js_proof)?; cx.export_function("groveDbClose", GroveDbWrapper::js_close)?; + cx.export_function("groveDbFlush", GroveDbWrapper::js_flush)?; + cx.export_function( + "groveDbStartTransaction", + GroveDbWrapper::js_start_transaction, + )?; + cx.export_function( + "groveDbCommitTransaction", + GroveDbWrapper::js_commit_transaction, + )?; + cx.export_function( + "groveDbRollbackTransaction", + GroveDbWrapper::js_rollback_transaction, + )?; + cx.export_function( + "groveDbIsTransactionStarted", + GroveDbWrapper::js_is_transaction_started, + )?; + cx.export_function( + "groveDbAbortTransaction", + GroveDbWrapper::js_abort_transaction, + )?; + cx.export_function("groveDbPutAux", GroveDbWrapper::js_put_aux)?; + cx.export_function("groveDbDeleteAux", GroveDbWrapper::js_delete_aux)?; + cx.export_function("groveDbGetAux", GroveDbWrapper::js_get_aux)?; + cx.export_function("groveDbGetPathQuery", GroveDbWrapper::js_get_path_query)?; + cx.export_function("groveDbRootHash", GroveDbWrapper::js_root_hash)?; Ok(()) } diff --git a/package-lock.json b/package-lock.json index a4b68b526..f657aeb85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,125 @@ { - "name": "@dashevo/node-grove", - "version": "0.0.2", + "name": "@dashevo/grovedb", + "version": "0.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "@dashevo/node-grove", - "version": "0.0.2", + "name": "@dashevo/grovedb", + "version": "0.2.0", "hasInstallScript": true, "license": "MIT", "dependencies": { - "cargo-cp-artifact": "^0.1.6" + "cargo-cp-artifact": "^0.1.6", + "neon-load-or-build": "^2.2.2", + "neon-tag-prebuild": "github:shumkov/neon-tag-prebuild#patch-1" }, "devDependencies": { "chai": "^4.3.4", - "mocha": "^8.4.0", - "rimraf": "^3.0.2" + "eslint": "^8.7.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-plugin-import": "^2.25.4", + "mocha": "^9.1.4" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", + "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.2.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.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/@humanwhocodes/config-array": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", + "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "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/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "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/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.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -34,12 +130,12 @@ } }, "node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "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": ">=4" + "node": ">=8" } }, "node_modules/ansi-styles": { @@ -76,6 +172,42 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -128,6 +260,28 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", @@ -203,24 +357,36 @@ } }, "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "dependencies": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { - "fsevents": "~2.3.1" + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/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/cliui": { @@ -234,50 +400,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/cliui/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/cliui/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/cliui/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/cliui/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/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -302,10 +424,30 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -349,6 +491,24 @@ "node": ">=0.12" } }, + "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/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -358,12 +518,75 @@ "node": ">=0.3.1" } }, + "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/es-abstract": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -385,131 +608,614 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/eslint": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", + "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "@eslint/eslintrc": "^1.0.5", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.0", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.2.0", + "espree": "^9.3.0", + "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": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "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", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" }, "engines": { - "node": ">=10" + "node": "^10.12.0 || >=12.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", "dev": true, - "bin": { - "flat": "cli.js" + "dependencies": { + "debug": "^3.2.7", + "resolve": "^1.20.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/eslint-module-utils": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.2.tgz", + "integrity": "sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg==", "dev": true, + "dependencies": { + "debug": "^3.2.7", + "find-up": "^2.1.0" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=4" } }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "node_modules/eslint-module-utils/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "locate-path": "^2.0.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "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==", + "node_modules/eslint-module-utils/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "node_modules/eslint-module-utils/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, "engines": { - "node": ">=4.x" + "node": ">=4" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "node_modules/eslint-module-utils/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.25.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", + "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.2", + "has": "^1.0.3", + "is-core-module": "^2.8.0", + "is-glob": "^4.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.5", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.12.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", + "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/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-visitor-keys": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", + "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/espree": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", + "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", + "dev": true, + "dependencies": { + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.1.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "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/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/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-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": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/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.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/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": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -519,6 +1225,40 @@ "he": "bin/he" } }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "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": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "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", @@ -535,6 +1275,32 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -547,6 +1313,61 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -557,12 +1378,12 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "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": ">=4" + "node": ">=8" } }, "node_modules/is-glob": { @@ -577,6 +1398,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -586,6 +1419,21 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -595,6 +1443,85 @@ "node": ">=8" } }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -602,9 +1529,9 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -613,6 +1540,43 @@ "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": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "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/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -628,16 +1592,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { @@ -652,34 +1626,50 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.1.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.4.tgz", + "integrity": "sha512-+q2aV5VlJZuLgCWoBvGI5zEwPF9eEI0kr/sAA9Jm4xMND7RfIEyF8JE7C0JIg8WXRG+P1sdIAb5ccoHPlXLzcw==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", + "chokidar": "3.5.2", + "debug": "4.3.2", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.1.25", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -689,13 +1679,36 @@ "mocha": "bin/mocha" }, "engines": { - "node": ">= 10.12.0" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mochajs" } }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -703,9 +1716,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -714,6 +1727,50 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/neon-load-or-build": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/neon-load-or-build/-/neon-load-or-build-2.2.2.tgz", + "integrity": "sha512-Muq74QiBaQO/Pi64XcqLjCh8vRriEo9rMvz/WvF+CFXTY0AgbD0vE14q4rmYsoJY+djav95JetHXyzaP+giaZg==", + "bin": { + "neon-load-or-build": "bin.js", + "neon-load-or-build-optional": "optional.js", + "neon-load-or-build-test": "build-test.js" + } + }, + "node_modules/neon-tag-prebuild": { + "version": "1.1.0", + "resolved": "git+ssh://git@github.com/shumkov/neon-tag-prebuild.git#a429834da27432b129eceb737e4d2b3f03fa5496", + "license": "MIT", + "dependencies": { + "mkdirp": "^1.0.4", + "node-abi": "^2.19.1" + }, + "bin": { + "neon-tag-prebuild": "bin.js" + } + }, + "node_modules/node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dependencies": { + "semver": "^5.4.1" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -723,13 +1780,97 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "dependencies": { - "wrappy": "1" + "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/p-limit": { @@ -762,6 +1903,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -780,6 +1942,21 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -790,9 +1967,9 @@ } }, "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "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" @@ -801,6 +1978,24 @@ "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/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -811,9 +2006,9 @@ } }, "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { "picomatch": "^2.2.1" @@ -822,6 +2017,18 @@ "node": ">=8.10.0" } }, + "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-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -831,6 +2038,32 @@ "node": ">=0.10.0" } }, + "node_modules/resolve": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz", + "integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-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/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -866,36 +2099,116 @@ } ] }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { "randombytes": "^2.1.0" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "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": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "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": "^3.0.0" + "ansi-regex": "^5.0.1" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, "engines": { "node": ">=4" } @@ -927,6 +2240,24 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "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", @@ -939,6 +2270,30 @@ "node": ">=8.0" } }, + "node_modules/tsconfig-paths": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -948,6 +2303,48 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -963,19 +2360,35 @@ "node": ">= 8" } }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, "dependencies": { - "string-width": "^1.0.2 || 2" + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "node_modules/wrap-ansi": { @@ -995,50 +2408,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1096,70 +2465,99 @@ "node": ">=10" } }, - "node_modules/yargs/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/yargs/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==", + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/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" + "node": ">=10" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + } + }, + "dependencies": { + "@eslint/eslintrc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", + "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.2.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" }, - "engines": { - "node": ">=8" + "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 + } } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "@humanwhocodes/config-array": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", + "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" } - } - }, - "dependencies": { + }, + "@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 + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "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": {} + }, + "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.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -1167,9 +2565,9 @@ "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "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": { @@ -1197,6 +2595,30 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + } + }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -1240,6 +2662,22 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", @@ -1293,19 +2731,30 @@ "dev": true }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } } }, "cliui": { @@ -1317,40 +2766,6 @@ "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "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 - }, - "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 - }, - "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" - } - } } }, "color-convert": { @@ -1374,10 +2789,27 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "requires": { "ms": "2.1.2" @@ -1406,18 +2838,81 @@ "type-detect": "^4.0.0" } }, + "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 + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, + "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 }, + "es-abstract": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -1430,6 +2925,294 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, + "eslint": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", + "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.0.5", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.0", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.2.0", + "espree": "^9.3.0", + "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": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "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", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-module-utils": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.2.tgz", + "integrity": "sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "find-up": "^2.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.25.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", + "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", + "dev": true, + "requires": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.2", + "has": "^1.0.3", + "is-core-module": "^2.8.0", + "is-glob": "^4.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.5", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.12.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-scope": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", + "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "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 + } + } + }, + "eslint-visitor-keys": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", + "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", + "dev": true + }, + "espree": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", + "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", + "dev": true, + "requires": { + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.1.0" + } + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "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" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "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-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": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "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", @@ -1455,6 +3238,22 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "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.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1468,6 +3267,18 @@ "dev": true, "optional": true }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "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": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1480,10 +3291,31 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -1495,12 +3327,21 @@ } }, "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" } }, "growl": { @@ -1509,16 +3350,68 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "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 }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "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": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "inflight": { @@ -1537,6 +3430,26 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1546,6 +3459,40 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1553,9 +3500,9 @@ "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "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": { @@ -1567,18 +3514,82 @@ "is-extglob": "^2.1.1" } }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1586,14 +3597,45 @@ "dev": true }, "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" } }, + "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": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "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" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1603,13 +3645,20 @@ "p-locate": "^5.0.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 + }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "minimatch": { @@ -1621,37 +3670,66 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, "mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.1.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.4.tgz", + "integrity": "sha512-+q2aV5VlJZuLgCWoBvGI5zEwPF9eEI0kr/sAA9Jm4xMND7RfIEyF8JE7C0JIg8WXRG+P1sdIAb5ccoHPlXLzcw==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", + "chokidar": "3.5.2", + "debug": "4.3.2", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.1.25", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "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 + } + } + } } }, "ms": { @@ -1661,17 +3739,97 @@ "dev": true }, "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "neon-load-or-build": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/neon-load-or-build/-/neon-load-or-build-2.2.2.tgz", + "integrity": "sha512-Muq74QiBaQO/Pi64XcqLjCh8vRriEo9rMvz/WvF+CFXTY0AgbD0vE14q4rmYsoJY+djav95JetHXyzaP+giaZg==" + }, + "neon-tag-prebuild": { + "version": "git+ssh://git@github.com/shumkov/neon-tag-prebuild.git#a429834da27432b129eceb737e4d2b3f03fa5496", + "from": "neon-tag-prebuild@github:shumkov/neon-tag-prebuild#patch-1", + "requires": { + "mkdirp": "^1.0.4", + "node-abi": "^2.19.1" + } + }, + "node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "requires": { + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1681,6 +3839,20 @@ "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" + } + }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -1699,6 +3871,21 @@ "p-limit": "^3.0.2" } }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -1711,6 +3898,18 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -1718,9 +3917,21 @@ "dev": true }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "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 + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, "randombytes": { @@ -1733,20 +3944,43 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" } }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "resolve": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz", + "integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==", + "dev": true, + "requires": { + "is-core-module": "^2.8.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "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 + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1762,34 +3996,93 @@ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.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 + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "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": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "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": "^3.0.0" + "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1805,6 +4098,18 @@ "has-flag": "^4.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1814,12 +4119,66 @@ "is-number": "^7.0.0" } }, + "tsconfig-paths": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "0.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 + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, + "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 + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1829,19 +4188,29 @@ "isexe": "^2.0.0" } }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, "requires": { - "string-width": "^1.0.2 || 2" + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" } }, + "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 + }, "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "wrap-ansi": { @@ -1853,40 +4222,6 @@ "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "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 - }, - "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 - }, - "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" - } - } } }, "wrappy": { @@ -1914,40 +4249,6 @@ "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" - }, - "dependencies": { - "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 - }, - "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 - }, - "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" - } - } } }, "yargs-parser": { diff --git a/package.json b/package.json index 67cb68457..462965b0b 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,24 @@ { - "name": "@dashevo/node-grove", - "version": "0.0.10", - "description": "Neon binding for GroveDb", + "name": "@dashevo/grovedb", + "version": "0.2.0", + "description": "Node.JS binding for GroveDb", "main": "node-grove/index.js", "readme": "node-grove/README.md", "scripts": { - "build": "cargo-cp-artifact -nc index.node -- cargo +nightly build --message-format=json-render-diagnostics", - "prepare": "mv README.md README.md.old && cp node-grove/README.md README.md", - "install": "npm run build", + "build": "cargo-cp-artifact -ac node-grove native/index.node -- cargo +nightly build --message-format=json-render-diagnostics", + "build:debug": "npm run build --", + "build:release": "npm run build -- --release", + "postbuild": "neon-tag-prebuild && mkdir -p node-grove/prebuilds && cp -R prebuilds/* node-grove/prebuilds/ && rm -rf native prebuilds", + "prepack": "mv README.md README.md.old && cp node-grove/README.md README.md", + "postpack": "rm README.md && mv README.md.old README.md", + "install": "neon-load-or-build", "clean": "cargo +nightly clean", + "pretest": "npm run build:debug", "test": "mocha node-grove/index.spec.js", - "postpublish": "rm README.md && mv README.md.old README.md" + "lint": "eslint ." }, "files": [ + "node-grove/prebuilds", "node-grove/index.js", "node-grove/src", "node-grove/Cargo.toml", @@ -21,14 +27,15 @@ "grovedb/Cargo.toml", "merk/src", "merk/Cargo.toml", - "Cargo.toml", - "Cargo.lock" + "Cargo.toml" ], "license": "MIT", "devDependencies": { "chai": "^4.3.4", - "mocha": "^8.4.0", - "rimraf": "^3.0.2" + "eslint": "^8.7.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-plugin-import": "^2.25.4", + "mocha": "^9.1.4" }, "repository": { "type": "git", @@ -44,6 +51,8 @@ }, "homepage": "https://github.com/dashevo/grovedb#readme", "dependencies": { - "cargo-cp-artifact": "^0.1.6" + "cargo-cp-artifact": "^0.1.6", + "neon-load-or-build": "^2.2.2", + "neon-tag-prebuild": "github:shumkov/neon-tag-prebuild#patch-1" } }