├── libcobhandemo ├── python-test │ ├── cobhan_demo_lib │ │ ├── __init__.py │ │ └── cobhan_demo.py │ └── consumer_console_app.py ├── node-test │ ├── libcobhandemo │ │ ├── .eslintrc.json │ │ ├── package.json │ │ └── index.js │ └── consumer-console-app │ │ ├── .eslintrc.json │ │ ├── package.json │ │ ├── index.js │ │ └── package-lock.json ├── Cargo.toml ├── src │ └── lib.rs └── build.sh ├── cobhan ├── build.sh ├── Cargo.toml └── src │ └── lib.rs ├── .gitignore ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── SECURITY.md ├── LICENSE ├── README.md ├── CODE_OF_CONDUCT.md └── CONTRIBUTING.md /libcobhandemo/python-test/cobhan_demo_lib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libcobhandemo/node-test/libcobhandemo/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es2021": true 6 | }, 7 | "extends": [ 8 | "google" 9 | ], 10 | "parserOptions": { 11 | "ecmaVersion": 12 12 | }, 13 | "rules": { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /libcobhandemo/node-test/consumer-console-app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es2021": true 6 | }, 7 | "extends": [ 8 | "google" 9 | ], 10 | "parserOptions": { 11 | "ecmaVersion": 12 12 | }, 13 | "rules": { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /libcobhandemo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cobhandemo" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | [dependencies] 7 | base64 = "0.13.0" 8 | cobhan = { path = "../cobhan" } 9 | rand = "0.8.4" 10 | serde_json = "1.0.68" 11 | 12 | [lib] 13 | name = "cobhandemo" 14 | crate-type = ["rlib", "cdylib"] 15 | 16 | [features] 17 | cobhan_debug = [] 18 | -------------------------------------------------------------------------------- /cobhan/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "${DEBUG:-0}" -eq "1" ]; then 4 | BUILD_FLAGS="--features cobhan_debug" 5 | else 6 | BUILD_FLAGS="--release" 7 | fi 8 | 9 | if [ "${ALPINE:-0}" -eq "1" ]; then 10 | BUILD_FLAGS="${BUILD_FLAGS} -C target-feature=-crt-static" 11 | fi 12 | 13 | # Build 14 | cargo build --verbose "${BUILD_FLAGS}" --target-dir target/ 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | node_modules/ 13 | binaries/ 14 | output/ 15 | -------------------------------------------------------------------------------- /libcobhandemo/node-test/consumer-console-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "consumer-console-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "libcobhandemo": "file:../libcobhandemo", 14 | "process": "^0.11.10" 15 | }, 16 | "devDependencies": { 17 | "eslint": "^7.32.0", 18 | "eslint-config-google": "^0.14.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /cobhan/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cobhan" 3 | version = "0.1.1" 4 | edition = "2018" 5 | authors = ["Jeremiah Gowdy ", "Jeremiah Senkpiel "] 6 | description = "Cobhan FFI is a system for enabling shared code to be written in Rust and consumed from all major languages/platforms in a safe and effective way, using easy helper functions to manage any unsafe data marshaling." 7 | readme = "../README.md" 8 | repository = "https://github.com/godaddy/cobhan-rust" 9 | license-file = "../LICENSE" 10 | homepage = "https://github.com/godaddy/cobhan-rust" 11 | 12 | [dependencies] 13 | libc = "0.2.103" 14 | serde_json = "1.0.68" 15 | tempfile = "3.2.0" 16 | 17 | [lib] 18 | name = "cobhan" 19 | crate-type = ["rlib"] 20 | 21 | [features] 22 | cobhan_debug = [] 23 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Issues 2 | 3 | We take security very seriously at GoDaddy. We appreciate your efforts to 4 | responsibly disclose your findings, and will make every effort to acknowledge 5 | your contributions. 6 | 7 | ## Where should I report security issues? 8 | 9 | In order to give the community time to respond and upgrade, we strongly urge you 10 | report all security issues privately. 11 | 12 | To report a security issue in one of our Open Source projects email us directly 13 | at **oss@godaddy.com** and include the word "SECURITY" in the subject line. 14 | 15 | This mail is delivered to our Open Source Security team. 16 | 17 | After the initial reply to your report, the team will keep you informed of the 18 | progress being made towards a fix and announcement, and may ask for additional 19 | information or guidance. 20 | -------------------------------------------------------------------------------- /libcobhandemo/node-test/libcobhandemo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libcobhandemo", 3 | "version": "1.2.2", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/jgowdy/cobhan.git" 13 | }, 14 | "keywords": [], 15 | "author": "Jeremiah Gowdy ", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/jgowdy/cobhan/issues" 19 | }, 20 | "homepage": "https://github.com/jgowdy/cobhan#readme", 21 | "files": [ 22 | "binaries/**/*.so", 23 | "binaries/**/*.dylib" 24 | ], 25 | "devDependencies": { 26 | "eslint": "^7.32.0", 27 | "eslint-config-google": "^0.14.0" 28 | }, 29 | "dependencies": { 30 | "cobhan": "^1.0.15" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libcobhandemo/node-test/consumer-console-app/index.js: -------------------------------------------------------------------------------- 1 | import libcobhandemo from 'libcobhandemo'; 2 | 3 | libcobhandemo.spawnThread() 4 | 5 | console.log('Start Counter: ' + libcobhandemo.readCounter()) 6 | 7 | console.log(libcobhandemo.toUpper('Initial value')); 8 | 9 | let output = libcobhandemo.filterJsonObject({ test: 'foo', test2: 'kittens' } , 'foo'); 10 | console.log(output); 11 | 12 | // Intentionally showing integer behavior Number is truncation, not rounding 13 | console.log(libcobhandemo.addInt32(2.9, 2.0)); 14 | console.log(libcobhandemo.addInt64(2.9, 2.0)); 15 | 16 | // Double is the same as Number 17 | console.log(libcobhandemo.addDouble(2.9, 2.0)); 18 | 19 | 20 | // Test using a Promise to call a blocking function 21 | console.log('Start sleeping'); 22 | libcobhandemo.sleepTest(2).then(() => { 23 | console.log('Finished sleeping'); 24 | console.log('Final Counter: ' + libcobhandemo.readCounter()); 25 | }) 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 GoDaddy Operating Company, LLC. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cobhan-rust - FFI Data Interface 2 | 3 | Cobhan FFI is a system for enabling shared code to be written in Rust and consumed from all major languages/platforms in a safe and effective way, using easy helper functions to manage any unsafe data marshaling. 4 | 5 | ## Types 6 | 7 | * Supported types 8 | * i32 - 32bit signed integer 9 | * i64 - 64bit signed integer 10 | * f64 - double precision 64bit IEEE 754 floating point 11 | * Cobhan buffer - length delimited 8bit buffer (no null delimiters) 12 | * utf-8 encoded string 13 | * JSON 14 | * binary data 15 | * Cobhan buffer details 16 | * Callers provide the output buffer allocation and capacity 17 | * Called functions can transparently return larger values via temporary files 18 | * **Modern [tmpfs](https://en.wikipedia.org/wiki/Tmpfs) is entirely memory backed** 19 | * Return values 20 | * Functions that return scalar values can return the value directly 21 | * Functions *can* use special case and return maximum positive or maximum negative or zero values to 22 | represent error or overflow conditions 23 | * Functions *can* allow scalar values to wrap 24 | * Functions should document their overflow / underflow behavior 25 | -------------------------------------------------------------------------------- /libcobhandemo/python-test/consumer_console_app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from cobhan_demo_lib.cobhan_demo import CobhanDemoLib 4 | 5 | lib_file = sys.argv[1] 6 | 7 | print(f"Testing: {lib_file}") 8 | 9 | if os.path.isfile(lib_file): 10 | lib = CobhanDemoLib.from_library_file(str(os.path.abspath(lib_file))) 11 | else: 12 | print("Library file is missing") 13 | sys.exit(255) 14 | 15 | print(f"Loaded: {lib_file}") 16 | 17 | counter = lib.read_counter() 18 | print(f"Counter: {counter}") 19 | 20 | print("Spawning thread") 21 | lib.spawn_thread() 22 | 23 | result = lib.to_upper('Initial value') 24 | if result != "INITIAL VALUE": 25 | print("to_upper test failed") 26 | sys.exit(255) 27 | 28 | result2 = lib.add_int32(1, 1) 29 | if result2 != 2: 30 | print("add_int32 test failed") 31 | sys.exit(255) 32 | 33 | result3 = lib.base64Encode("Test") 34 | if result3 != "VGVzdA==": 35 | print("base64Encode test failed") 36 | sys.exit(255) 37 | 38 | result4 = lib.filterJson({'test': 'foo', 'test2': 'kittens'}, 'foo') 39 | if result4["test2"] != "kittens": 40 | print("filterJson test failed") 41 | sys.exit(255) 42 | 43 | print("Testing sleep_test(3)") 44 | lib.sleep_test(2) 45 | 46 | counter = lib.read_counter() 47 | print(f"Counter: {counter}") 48 | 49 | print(f"Passed: {lib_file}") 50 | 51 | 52 | -------------------------------------------------------------------------------- /libcobhandemo/python-test/cobhan_demo_lib/cobhan_demo.py: -------------------------------------------------------------------------------- 1 | from cobhan.cobhan import Cobhan 2 | 3 | class CobhanDemoLib(Cobhan): 4 | CDEFINES = """ 5 | void sleepTest(int32_t seconds); 6 | int32_t addInt32(int32_t x, int32_t y); 7 | int64_t addInt64(int64_t x, int64_t y); 8 | double addDouble(double x, double y); 9 | int32_t toUpper(void *input, void *output); 10 | int32_t filterJson(void *input, void *disallowedValue, void *output); 11 | int32_t base64Encode(void *input, void *output); 12 | void spawnThread(); 13 | int32_t readCounter(); 14 | """ 15 | 16 | @classmethod 17 | def from_library_path(cls, library_root_path): 18 | instance = cls() 19 | instance.load_library(library_root_path, 'libcobhandemo', CobhanDemoLib.CDEFINES) 20 | return instance 21 | 22 | @classmethod 23 | def from_library_file(cls, library_file_path): 24 | instance = cls() 25 | instance.load_library_direct(library_file_path, CobhanDemoLib.CDEFINES) 26 | return instance 27 | 28 | def to_upper(self, input): 29 | in_buf = self.str_to_buf(input) 30 | out_buf = self.allocate_buf(len(in_buf)) 31 | 32 | result = self._lib.toUpper(in_buf, out_buf) 33 | if result < 0: 34 | raise Exception(f"toUpper failed {result}") 35 | 36 | return self.buf_to_str(out_buf) 37 | 38 | def spawn_thread(self): 39 | self._lib.spawnThread() 40 | 41 | def read_counter(self): 42 | return self._lib.readCounter() 43 | 44 | def sleep_test(self, seconds): 45 | self._lib.sleepTest(seconds) 46 | 47 | def add_int32(self, x, y): 48 | return self._lib.addInt32(x, y) 49 | 50 | def add_int64(self, x, y): 51 | return self._lib.addInt64(x, y) 52 | 53 | def add_double(self, x, y): 54 | return self._lib.addDouble(x, y) 55 | 56 | def filterJson(self, input, disallowed): 57 | input_buf = self.to_json_buf(input) 58 | 59 | disallowed_buf = self.str_to_buf(disallowed) 60 | 61 | output_len = int(len(input_buf) * 1.5) # Allow extra space for reformatting 62 | output_buf = self.allocate_buf(output_len) 63 | 64 | result = self._lib.filterJson(input_buf, disallowed_buf, output_buf) 65 | if result < 0: 66 | raise Exception(f"filterJson failed {result}") 67 | 68 | return self.from_json_buf(output_buf) 69 | 70 | def base64Encode(self, input): 71 | input_buf = self.str_to_buf(input) 72 | output_len = int((4 * len(input_buf) / 3) + 3) & ~3 73 | output_buf = self.allocate_buf(output_len) 74 | 75 | result = self._lib.base64Encode(input_buf, output_buf) 76 | if result < 0: 77 | raise Exception(f"base64Encode failed {result}") 78 | 79 | return self.buf_to_str(output_buf) 80 | -------------------------------------------------------------------------------- /libcobhandemo/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::missing_safety_doc)] 2 | 3 | use std::collections::HashMap; 4 | use std::os::raw::c_char; 5 | use std::sync::atomic::{AtomicI32, Ordering}; 6 | use std::{thread, time}; 7 | 8 | use rand::Rng; 9 | use rand::RngCore; 10 | use serde_json::Value; 11 | 12 | static COUNTER: AtomicI32 = AtomicI32::new(0); 13 | 14 | #[no_mangle] 15 | pub unsafe extern "C" fn spawnThread() { 16 | std::thread::spawn(move || loop { 17 | COUNTER.fetch_add(1, Ordering::Relaxed); 18 | thread::sleep(time::Duration::from_secs(1)) 19 | }); 20 | } 21 | 22 | #[no_mangle] 23 | pub unsafe extern "C" fn readCounter() -> i32 { 24 | COUNTER.load(Ordering::Relaxed) 25 | } 26 | 27 | #[no_mangle] 28 | pub unsafe extern "C" fn sleepTest(seconds: i32) { 29 | thread::sleep(time::Duration::from_secs(seconds as u64)) 30 | } 31 | 32 | #[no_mangle] 33 | pub unsafe extern "C" fn addInt32(x: i32, y: i32) -> i32 { 34 | x.saturating_add(y) 35 | } 36 | 37 | #[no_mangle] 38 | pub unsafe extern "C" fn addInt64(x: i64, y: i64) -> i64 { 39 | x.saturating_add(y) 40 | } 41 | 42 | #[no_mangle] 43 | pub unsafe extern "C" fn addDouble(x: f64, y: f64) -> f64 { 44 | x + y 45 | } 46 | 47 | #[no_mangle] 48 | pub unsafe extern "C" fn toUpper(input: *const c_char, output: *mut c_char) -> i32 { 49 | let input_str = match cobhan::cbuffer_to_string(input) { 50 | Ok(s) => s, 51 | Err(e) => return e, 52 | }; 53 | 54 | let output_str = input_str.to_uppercase(); 55 | 56 | cobhan::string_to_cbuffer(&output_str, output) 57 | } 58 | 59 | #[no_mangle] 60 | pub unsafe extern "C" fn filterJson( 61 | input: *const c_char, 62 | disallowed_value: *const c_char, 63 | output: *mut c_char, 64 | ) -> i32 { 65 | let mut json; 66 | match cobhan::cbuffer_to_hashmap_json(input) { 67 | Ok(input_json) => json = input_json, 68 | Err(e) => return e, 69 | } 70 | 71 | let disallowed_value_str = match cobhan::cbuffer_to_string(disallowed_value) { 72 | Ok(disallow) => disallow, 73 | Err(e) => return e, 74 | }; 75 | 76 | filter_json(&mut json, &disallowed_value_str); 77 | 78 | cobhan::hashmap_json_to_cbuffer(&json, output) 79 | } 80 | 81 | // Example of a safe function 82 | pub fn filter_json(json: &mut HashMap, disallowed: &str) { 83 | json.retain(|_key, value| matches!(value, Value::String(s) if !s.contains(&disallowed))); 84 | } 85 | 86 | #[no_mangle] 87 | pub unsafe extern "C" fn base64Encode(input: *const c_char, output: *mut c_char) -> i32 { 88 | let bytes = match cobhan::cbuffer_to_vector(input) { 89 | Ok(b) => b, 90 | Err(e) => return e, 91 | }; 92 | 93 | let b64str = base64::encode(bytes); 94 | 95 | cobhan::string_to_cbuffer(&b64str, output) 96 | } 97 | 98 | #[no_mangle] 99 | pub unsafe extern "C" fn generateRandom(output: *mut c_char) -> i32 { 100 | let mut rng = rand::thread_rng(); 101 | let size = rng.gen_range(0..134217728); 102 | let mut bytes: Vec = vec![0; size]; 103 | rng.fill_bytes(&mut bytes); 104 | cobhan::bytes_to_cbuffer(&bytes, output) 105 | } 106 | -------------------------------------------------------------------------------- /libcobhandemo/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # If DEBUG is set, add debug- to the file names 5 | if [ "${DEBUG:-0}" -eq "1" ]; then 6 | DEBUG_FN_PART="debug-" 7 | else 8 | DEBUG_FN_PART="" 9 | fi 10 | 11 | # Normalize machine architecture for file names 12 | case $(uname -m) in 13 | "x86_64") 14 | SYS_FN_PART="x64" 15 | ;; 16 | "aarch64") 17 | SYS_FN_PART="arm64" 18 | ;; 19 | "arm64") 20 | SYS_FN_PART="arm64" 21 | ;; 22 | *) 23 | echo "Unknown machine $(uname -m)!" 24 | exit 255 25 | ;; 26 | esac 27 | 28 | # If ALPINE is set, include musl in the file name 29 | if [ "${ALPINE:-0}" -eq "1" ]; then 30 | SYS_FN_PART="musl-${SYS_FN_PART}" 31 | fi 32 | 33 | # OS Detection 34 | case $(uname -s) in 35 | "Darwin") 36 | IS_MACOS=1 37 | DYN_EXT=".dylib" 38 | RUST_EXT="-darwin.rlib" 39 | A_EXT="-darwin.a" 40 | ;; 41 | "Linux") 42 | IS_MACOS=0 43 | DYN_EXT=".so" 44 | RUST_EXT=".rlib" 45 | A_EXT=".a" 46 | ;; 47 | *) 48 | echo "Unknown system $(uname -s)!" 49 | exit 255 50 | ;; 51 | esac 52 | export IS_MACOS 53 | export DYN_EXT 54 | export RUST_EXT 55 | export A_EXT 56 | 57 | # Create dynamic library file name suffix 58 | DYN_SUFFIX="${DEBUG_FN_PART}${SYS_FN_PART}${DYN_EXT}" 59 | export DYN_SUFFIX 60 | 61 | # Create Rust static library file name suffix 62 | RLIB_SUFFIX="${DEBUG_FN_PART}${SYS_FN_PART}${RUST_EXT}" 63 | export RLIB_SUFFIX 64 | 65 | if [ "${DEBUG:-0}" -eq "1" ]; then 66 | BUILD_FLAGS="--features cobhan_debug" 67 | BUILD_DIR="debug" 68 | else 69 | BUILD_FLAGS="--release" 70 | BUILD_DIR="release" 71 | fi 72 | 73 | if [ "${ALPINE:-0}" -eq "1" ]; then 74 | RUSTFLAGS="-C target-feature=-crt-static" 75 | export RUSTFLAGS 76 | fi 77 | 78 | # Build 79 | echo "Compiling (Rust) ${BUILD_DIR}/libcobhandemo${DYN_EXT}" 80 | cargo build --verbose ${BUILD_FLAGS} --target-dir target/ 81 | 82 | # Test Rust dynamic library file using python 83 | 84 | pip install cobhan 85 | 86 | count=0 87 | while [ $count -lt 20 ]; do 88 | echo "Test iteration ${count}" 89 | python3 python-test/consumer_console_app.py "target/${BUILD_DIR}/libcobhandemo${DYN_EXT}" 90 | if [ "$?" -eq "0" ]; then 91 | echo "Passed" 92 | else 93 | echo "Tests failed (Rust): libcobhandemo-${DYN_SUFFIX} Result: $?" 94 | exit 255 95 | fi 96 | count=$(expr ${count} + 1) 97 | done 98 | 99 | ########## 100 | # Test Rust dynamic library file using node 101 | 102 | mkdir -p node-test/libcobhandemo/binaries/ 103 | cp "target/${BUILD_DIR}/libcobhandemo${DYN_EXT}" "node-test/libcobhandemo/binaries/libcobhandemo-${DYN_SUFFIX}" 104 | npm -C node-test/libcobhandemo install 105 | pushd node-test/consumer-console-app 106 | npm install 107 | count=0 108 | while [ $count -lt 20 ]; do 109 | echo "Test iteration ${count}" 110 | node . 111 | if [ "$?" -eq "0" ]; then 112 | echo "Passed" 113 | else 114 | echo "Tests failed (Rust): libcobhandemo-${DYN_SUFFIX} Result: $?" 115 | exit 255 116 | fi 117 | count=$(expr ${count} + 1) 118 | done 119 | popd 120 | ########## 121 | 122 | echo "Tests passed (Rust): libcobhandemo-${DYN_SUFFIX}" 123 | 124 | # Create output directory 125 | mkdir -p ./output/ 126 | 127 | # Copy Rust dynamic library file 128 | cp "target/${BUILD_DIR}/libcobhandemo${DYN_EXT}" "output/libcobhandemo-${DYN_SUFFIX}" 129 | 130 | # Copy Rust static library file 131 | cp "target/${BUILD_DIR}/libcobhandemo.rlib" "output/libcobhandemo-${RLIB_SUFFIX}" 132 | -------------------------------------------------------------------------------- /libcobhandemo/node-test/libcobhandemo/index.js: -------------------------------------------------------------------------------- 1 | import cobhan from 'cobhan' 2 | 3 | const libcobhandemo = cobhan.load_platform_library('node_modules/libcobhandemo/binaries', 'libcobhandemo', { 4 | 'sleepTest': ['void', ['int32']], 5 | 'addInt32': ['int32', ['int32', 'int32']], 6 | 'addInt64': ['int64', ['int64', 'int64']], 7 | 'addDouble': ['double', ['double', 'double']], 8 | 'toUpper': ['int32', ['pointer', 'pointer']], 9 | 'filterJson': ['int32', ['pointer', 'pointer', 'pointer']], 10 | 'spawnThread': ['void', []], 11 | 'readCounter': ['int32', []] 12 | }); 13 | 14 | function spawnThread() { 15 | libcobhandemo.spawnThread(); 16 | } 17 | 18 | /** 19 | * @return {number} 20 | */ 21 | function readCounter() { 22 | return libcobhandemo.readCounter(); 23 | } 24 | 25 | /** 26 | * @param {object} input 27 | * @param {string} disallowedValue 28 | * @return {object} 29 | */ 30 | function filterJsonObject(input, disallowedValue) { 31 | const json = JSON.stringify(input); 32 | const inputBuffer = cobhan.string_to_cbuffer(json); 33 | const disallowedBuffer = cobhan.string_to_cbuffer(disallowedValue); 34 | const outputBuffer = cobhan.allocate_cbuffer(json.length); 35 | 36 | const result = libcobhandemo.filterJson(inputBuffer, disallowedBuffer, outputBuffer); 37 | if (result < 0) { 38 | throw new Error('filterJson failed: ' + result); 39 | } 40 | 41 | return JSON.parse(cobhan.cbuffer_to_string(outputBuffer)); 42 | } 43 | 44 | /** 45 | * @param {string} inputJson 46 | * @param {string} disallowedValue 47 | * @return {string} 48 | */ 49 | function filterJsonString(inputJson, disallowedValue) { 50 | const inputBuffer = cobhan.string_to_cbuffer(inputJson); 51 | const disallowedBuffer = cobhan.string_to_cbuffer(disallowedValue); 52 | const outputBuffer = cobhan.allocate_cbuffer(inputJson.length); 53 | 54 | const result = libcobhandemo.filterJson(inputBuffer, disallowedBuffer, outputBuffer); 55 | if (result < 0) { 56 | throw new Error('filterJson failed: ' + result); 57 | } 58 | 59 | return cobhan.cbuffer_to_string(outputBuffer); 60 | } 61 | 62 | /** 63 | * @param {string} input 64 | * @return {string} 65 | */ 66 | function toUpper(input) { 67 | const inputBuffer = cobhan.string_to_cbuffer(input); 68 | const outputBuffer = cobhan.allocate_cbuffer(input.length); 69 | 70 | const result = libcobhandemo.toUpper(inputBuffer, outputBuffer); 71 | if (result < 0) { 72 | throw new Error('toUpper failed: ' + result); 73 | } 74 | 75 | return cobhan.cbuffer_to_string(outputBuffer); 76 | } 77 | 78 | /** 79 | * @param {number} x 80 | * @param {number} y 81 | * @return {number} 82 | */ 83 | function addInt32(x, y) { 84 | return libcobhandemo.addInt32(x, y); 85 | } 86 | 87 | /** 88 | * @param {number} x 89 | * @param {number} y 90 | * @return {number} 91 | */ 92 | function addInt64(x, y) { 93 | return libcobhandemo.addInt64(x, y); 94 | } 95 | 96 | /** 97 | * @param {number} x 98 | * @param {number} y 99 | * @return {number} 100 | */ 101 | function addDouble(x, y) { 102 | return libcobhandemo.addDouble(x, y); 103 | } 104 | 105 | /** 106 | * @param {number} seconds 107 | * @return {Promise} 108 | */ 109 | function sleepTest(seconds) { 110 | return new Promise((resolve) => { 111 | libcobhandemo.sleepTest.async(seconds, () => { 112 | resolve(); 113 | }); 114 | }); 115 | } 116 | 117 | export default { spawnThread, readCounter, filterJsonObject, filterJsonString, toUpper, sleepTest, addInt32, addInt64, addDouble }; 118 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at oss@godaddy.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | 78 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Everyone is welcome to contribute to GoDaddy's Open Source Software. 4 | Contributing doesn’t just mean submitting pull requests. To get involved, 5 | you can report or triage bugs, and participate in discussions on the 6 | evolution of each project. 7 | 8 | No matter how you want to get involved, we ask that you first learn what’s 9 | expected of anyone who participates in the project by reading the Contribution 10 | Guidelines and our [Code of Conduct][coc]. 11 | 12 | ## Answering Questions 13 | 14 | One of the most important and immediate ways you can support this project is 15 | to answer questions on [Github][issues]. Whether you’re 16 | helping a newcomer understand a feature or troubleshooting an edge case with a 17 | seasoned developer, your knowledge and experience with a programming language 18 | can go a long way to help others. 19 | 20 | ## Reporting Bugs 21 | 22 | **Do not report potential security vulnerabilities here. Refer to 23 | [SECURITY.md](./SECURITY.md) for more details about the process of reporting 24 | security vulnerabilities.** 25 | 26 | Before submitting a ticket, please search our [Issue Tracker][issues] to make 27 | sure it does not already exist and have a simple replication of the behavior. If 28 | the issue is isolated to one of the dependencies of this project, please create 29 | a Github issue in that project. All dependencies should be open source software 30 | and can be found on Github. 31 | 32 | Submit a ticket for your issue, assuming one does not already exist: 33 | 34 | - Create it on the project's [issue Tracker][issues]. 35 | - Clearly describe the issue by following the template layout 36 | - Make sure to include steps to reproduce the bug. 37 | - A reproducible (unit) test could be helpful in solving the bug. 38 | - Describe the environment that (re)produced the problem. 39 | 40 | ## Triaging bugs or contributing code 41 | 42 | If you're triaging a bug, first make sure that you can reproduce it. Once a bug 43 | can be reproduced, reduce it to the smallest amount of code possible. Reasoning 44 | about a sample or unit test that reproduces a bug in just a few lines of code 45 | is easier than reasoning about a longer sample. 46 | 47 | From a practical perspective, contributions are as simple as: 48 | 49 | 1. Fork and clone the repo, [see Github's instructions if you need help.][fork] 50 | 1. Create a branch for your PR with `git checkout -b pr/your-branch-name` 51 | 1. Make changes on the branch of your forked repository. 52 | 1. When committing, reference your issue (if present) and include a note about 53 | the fix. 54 | 1. Please also add/update unit tests for your changes. 55 | 1. Push the changes to your fork and submit a pull request to the 'main 56 | development branch' branch of the projects' repository. 57 | 58 | If you are interested in making a large change and feel unsure about its overall 59 | effect, start with opening an Issue in the project's [Issue Tracker][issues] 60 | with a high-level proposal and discuss it with the core contributors through 61 | Github comments. After reaching a consensus with core 62 | contributors about the change, discuss the best way to go about implementing it. 63 | 64 | > Tip: Keep your main branch pointing at the original repository and make 65 | > pull requests from branches on your fork. To do this, run: 66 | > 67 | > ```sh 68 | > git remote add upstream https://github.com/godaddy/cobhan-rust.git 69 | > git fetch upstream 70 | > git branch --set-upstream-to=upstream/main main 71 | > ``` 72 | > 73 | > This will add the original repository as a "remote" called "upstream," Then 74 | > fetch the git information from that remote, then set your local main 75 | > branch to use the upstream main branch whenever you run git pull. Then you 76 | > can make all of your pull request branches based on this main branch. 77 | > Whenever you want to update your version of main, do a regular git pull. 78 | 79 | ## Code Review 80 | 81 | Any open source project relies heavily on code review to improve software 82 | quality. All significant changes, by all developers, must be reviewed before 83 | they are committed to the repository. Code reviews are conducted on GitHub 84 | through comments on pull requests or commits. The developer responsible for a 85 | code change is also responsible for making all necessary review-related changes. 86 | 87 | Sometimes code reviews will take longer than you would hope for, especially for 88 | larger features. Here are some accepted ways to speed up review times for your 89 | patches: 90 | 91 | - Review other people’s changes. If you help out, others will more likely be 92 | willing to do the same for you. 93 | - Split your change into multiple smaller changes. The smaller your change, 94 | the higher the probability that somebody will take a quick look at it. 95 | 96 | **Note that anyone is welcome to review and give feedback on a change, but only 97 | people with commit access to the repository can approve it.** 98 | 99 | ## Attribution of Changes 100 | 101 | When contributors submit a change to this project, after that change is 102 | approved, other developers with commit access may commit it for the author. When 103 | doing so, it is important to retain correct attribution of the contribution. 104 | Generally speaking, Git handles attribution automatically. 105 | 106 | ## Code Style and Documentation 107 | 108 | Ensure that your contribution follows the standards set by the project's style 109 | guide with respect to patterns, naming, documentation and testing. 110 | 111 | # Additional Resources 112 | 113 | - [General GitHub Documentation](https://help.github.com/) 114 | - [GitHub Pull Request documentation](https://help.github.com/send-pull-requests/) 115 | 116 | [issues]: https://github.com/godaddy/cobhan-rust/issues/ 117 | [coc]: ./CODE_OF_CONDUCT.md 118 | [fork]: https://help.github.com/en/articles/fork-a-repo 119 | -------------------------------------------------------------------------------- /cobhan/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # cobhan-rust - FFI Data Interface 2 | //! 3 | //! Cobhan FFI is a system for enabling shared code to be written in Rust and 4 | //! consumed from all major languages/platforms in a safe and effective way, 5 | //! using easy helper functions to manage any unsafe data marshaling. 6 | //! 7 | //! ## Types 8 | //! 9 | //! * Supported types 10 | //! * i32 - 32bit signed integer 11 | //! * i64 - 64bit signed integer 12 | //! * fl64 - double precision 64bit IEEE 754 floating point 13 | //! * Cobhan buffer - length delimited 8bit buffer (no null delimiters) 14 | //! * utf-8 encoded string 15 | //! * JSON 16 | //! * binary data 17 | //! * Cobhan buffer details 18 | //! * Callers provide the output buffer allocation and capacity 19 | //! * Called functions can transparently return larger values via temporary files 20 | //! * **Modern [tmpfs](https://en.wikipedia.org/wiki/Tmpfs) is entirely memory backed** 21 | //! * Return values 22 | //! * Functions that return scalar values can return the value directly 23 | //! * Functions *can* use special case and return maximum positive or maximum negative or zero values to 24 | //! represent error or overflow conditions 25 | //! * Functions *can* allow scalar values to wrap 26 | //! * Functions should document their overflow / underflow behavior 27 | 28 | use std::borrow::Cow; 29 | use std::collections::HashMap; 30 | use std::fs; 31 | use std::io::Write; 32 | use std::os::raw::c_char; 33 | use std::ptr::copy_nonoverlapping; 34 | use std::slice::from_raw_parts; 35 | use std::str; 36 | 37 | use serde_json::Value; 38 | use tempfile::NamedTempFile; 39 | 40 | /// No Error 41 | pub const ERR_NONE: i32 = 0; 42 | 43 | /// One of the provided pointers is NULL / nil / 0 44 | pub const ERR_NULL_PTR: i32 = -1; 45 | 46 | /// One of the provided buffer lengths is too large 47 | pub const ERR_BUFFER_TOO_LARGE: i32 = -2; 48 | 49 | /// One of the provided buffers was too small 50 | pub const ERR_BUFFER_TOO_SMALL: i32 = -3; 51 | 52 | /// Failed to copy a buffer (copy length != expected length) 53 | pub const ERR_COPY_FAILED: i32 = -4; 54 | 55 | /// Failed to decode a JSON buffer 56 | pub const ERR_JSON_DECODE_FAILED: i32 = -5; 57 | 58 | /// Failed to encode to JSON buffer 59 | pub const ERR_JSON_ENCODE_FAILED: i32 = -6; 60 | 61 | /// UTF8 in a String or JSON is invalid. 62 | pub const ERR_INVALID_UTF8: i32 = -7; 63 | 64 | /// TempFile for large partial data failed to read. 65 | pub const ERR_READ_TEMP_FILE_FAILED: i32 = -8; 66 | 67 | /// TempFile for large partial data failed to write. 68 | pub const ERR_WRITE_TEMP_FILE_FAILED: i32 = -9; 69 | 70 | /// 64 bit buffer header provides 8 byte alignment for data pointers 71 | pub const BUFFER_HEADER_SIZE: isize = 64 / 8; 72 | 73 | const SIZEOF_INT32: isize = 32 / 8; 74 | 75 | #[cfg(feature = "cobhan_debug")] 76 | macro_rules! debug_print { 77 | ($( $args:expr ),*) => { println!($($args ),*); }; 78 | } 79 | 80 | #[cfg(not(feature = "cobhan_debug"))] 81 | macro_rules! debug_print { 82 | ($( $args:expr ),*) => {}; 83 | } 84 | 85 | /// Takes a pointer to an external Cobhan Buffer and fallibly attempts to interpret it as a `Vec`. 86 | /// 87 | /// ## Notes 88 | /// 89 | /// This function does a memcopy from the provided Cobhan Buffer into Rust owned data. 90 | /// 91 | /// ## Safety 92 | /// 93 | /// Behavior is undefined if any of the following conditions are violated: 94 | /// - The Cobhan Buffer Header size is not correctly reserved or formatted. 95 | /// - Any of the Safety conditions of [`std::slice::from_raw_parts`][] is violated. 96 | pub unsafe fn cbuffer_to_vector(buffer: *const c_char) -> Result, i32> { 97 | if buffer.is_null() { 98 | debug_print!("cbuffer_to_vector: buffer is NULL"); 99 | return Err(ERR_NULL_PTR); 100 | } 101 | let length = *(buffer as *const i32); 102 | let _reserved = buffer.offset(SIZEOF_INT32) as *const i32; 103 | let payload = buffer.offset(BUFFER_HEADER_SIZE) as *const u8; 104 | debug_print!("cbuffer_to_vector: raw length field is {}", length); 105 | 106 | if length < 0 { 107 | debug_print!("cbuffer_to_vector: calling temp_to_vector"); 108 | return temp_to_vector(payload, length); 109 | } 110 | 111 | //Allocation: to_vec() is a clone/copy 112 | Ok(from_raw_parts(payload, length as usize).to_vec()) 113 | } 114 | 115 | /// Takes a pointer to an external Cobhan Buffer and fallibly attempts to interpret it as a `String`. 116 | /// 117 | /// The String is fallibly checked to ensure UTF-8 formatting. 118 | /// 119 | /// ## Notes 120 | /// 121 | /// This function does a memcopy from the provided Cobhan Buffer into Rust owned data. 122 | /// 123 | /// ## Safety 124 | /// 125 | /// Behavior is undefined if any of the following conditions are violated: 126 | /// - The Cobhan Buffer Header size is not correctly reserved or formatted. 127 | /// - Any of the Safety conditions of [`std::slice::from_raw_parts`][] is violated. 128 | pub unsafe fn cbuffer_to_string(buffer: *const c_char) -> Result { 129 | if buffer.is_null() { 130 | debug_print!("cbuffer_to_string: buffer is NULL"); 131 | return Err(ERR_NULL_PTR); 132 | } 133 | let length = *(buffer as *const i32); 134 | let _reserved = buffer.offset(SIZEOF_INT32) as *const i32; 135 | let payload = buffer.offset(BUFFER_HEADER_SIZE) as *const u8; 136 | debug_print!("cbuffer_to_string: raw length field is {}", length); 137 | 138 | debug_print!("cbuffer_to_string: raw length field is {}", length); 139 | 140 | if length < 0 { 141 | debug_print!("cbuffer_to_string: calling temp_to_string"); 142 | return temp_to_string(payload, length); 143 | } 144 | 145 | str::from_utf8(from_raw_parts(payload, length as usize)) 146 | .map(|s| s.to_owned()) 147 | .map_err(|_| { 148 | debug_print!( 149 | "cbuffer_to_string: payload is invalid utf-8 string (length = {})", 150 | length 151 | ); 152 | ERR_INVALID_UTF8 153 | }) 154 | } 155 | 156 | /// Gets a tempfile data for a payload and interprets it as a `String`. 157 | unsafe fn temp_to_string(payload: *const u8, length: i32) -> Result { 158 | let file_name = 159 | str::from_utf8(from_raw_parts(payload, (0 - length) as usize)).map_err(|_| { 160 | debug_print!( 161 | "temp_to_string: temp file name is invalid utf-8 string (length = {})", 162 | 0 - length 163 | ); 164 | ERR_INVALID_UTF8 165 | })?; 166 | 167 | debug_print!("temp_to_string: reading temp file {}", file_name); 168 | 169 | fs::read_to_string(file_name).map_err(|_e| { 170 | debug_print!( 171 | "temp_to_string: Error reading temp file {}: {}", 172 | file_name, 173 | _e 174 | ); 175 | ERR_READ_TEMP_FILE_FAILED 176 | }) 177 | } 178 | 179 | /// Gets a tempfile data for a payload and interprets it as a `Vec`. 180 | unsafe fn temp_to_vector(payload: *const u8, length: i32) -> Result, i32> { 181 | let file_name = 182 | str::from_utf8(from_raw_parts(payload, (0 - length) as usize)).map_err(|_| { 183 | debug_print!( 184 | "temp_to_vector: temp file name is invalid utf-8 string (length = {})", 185 | 0 - length 186 | ); 187 | ERR_INVALID_UTF8 188 | })?; 189 | 190 | fs::read(file_name).map_err(|_e| { 191 | debug_print!( 192 | "temp_to_vector: failed to read temporary file {}: {}", 193 | file_name, 194 | _e 195 | ); 196 | ERR_READ_TEMP_FILE_FAILED 197 | }) 198 | } 199 | 200 | /// Takes a pointer to an external Cobhan Buffer and fallibly attempts to interpret it as a `Hashmap`. 201 | /// 202 | /// The JSON is fallibly checked to ensure UTF-8 formatting of any string properties. 203 | /// 204 | /// ## Notes 205 | /// 206 | /// This function does a memcopy from the provided Cobhan Buffer into Rust owned data. 207 | /// 208 | /// ## Safety 209 | /// 210 | /// Behavior is undefined if any of the following conditions are violated: 211 | /// - The Cobhan Buffer Header size is not correctly reserved or formatted. 212 | /// - Any of the Safety conditions of [`std::slice::from_raw_parts`][] is violated. 213 | pub unsafe fn cbuffer_to_hashmap_json( 214 | buffer: *const c_char, 215 | ) -> Result, i32> { 216 | if buffer.is_null() { 217 | debug_print!("cbuffer_to_hashmap_json: buffer is NULL"); 218 | return Err(ERR_NULL_PTR); 219 | } 220 | let length = *(buffer as *const i32); 221 | let _reserved = buffer.offset(SIZEOF_INT32) as *const i32; 222 | let payload = buffer.offset(BUFFER_HEADER_SIZE) as *const u8; 223 | debug_print!("cbuffer_to_hashmap_json: raw length field is {}", length); 224 | 225 | let json_bytes = if length >= 0 { 226 | Cow::Borrowed(from_raw_parts(payload, length as usize)) 227 | } else { 228 | debug_print!("cbuffer_to_hashmap_json: calling temp_to_vector"); 229 | Cow::Owned(temp_to_vector(payload, length)?) 230 | }; 231 | 232 | serde_json::from_slice(&json_bytes).map_err(|_e| { 233 | debug_print!( 234 | "cbuffer_to_hashmap_json: serde_json::from_slice / JSON decode failed {}", 235 | _e 236 | ); 237 | ERR_JSON_DECODE_FAILED 238 | }) 239 | } 240 | 241 | /// Takes a `Hashmap` and fallibly encodes it in JSON into a provided external Cobhan Buffer. 242 | /// 243 | /// The JSON is fallibly checked to ensure UTF-8 formatting of any string properties. 244 | /// 245 | /// Will cause an error code if the provided Cobhan Buffer is too small. 246 | /// 247 | /// ## Notes 248 | /// 249 | /// This function does a memcopy from the Rust data into the provided Cobhan Buffer. 250 | /// 251 | /// ## Safety 252 | /// 253 | /// Behavior is undefined if any of the following conditions are violated: 254 | /// - The Cobhan Buffer Header size is not correctly reserved or formatted. 255 | /// - Any of the Safety conditions of [`std::slice::from_raw_parts`][] is violated. 256 | pub unsafe fn hashmap_json_to_cbuffer(json: &HashMap, buffer: *mut c_char) -> i32 { 257 | match serde_json::to_vec(&json) { 258 | Ok(json_bytes) => bytes_to_cbuffer(&json_bytes, buffer), 259 | Err(_) => ERR_JSON_ENCODE_FAILED, 260 | } 261 | } 262 | 263 | /// Takes a `String` and fallibly encodes it into a provided external Cobhan Buffer. 264 | /// 265 | /// Will cause an error code if the provided Cobhan Buffer is too small. 266 | /// 267 | /// ## Notes 268 | /// 269 | /// This function does a memcopy from the Rust data into the provided Cobhan Buffer. 270 | /// 271 | /// ## Safety 272 | /// 273 | /// Behavior is undefined if any of the following conditions are violated: 274 | /// - The Cobhan Buffer Header size is not correctly reserved or formatted. 275 | /// - Any of the Safety conditions of [`std::slice::from_raw_parts`][] is violated. 276 | pub unsafe fn string_to_cbuffer(string: &str, buffer: *mut c_char) -> i32 { 277 | bytes_to_cbuffer(string.as_bytes(), buffer) 278 | } 279 | 280 | /// Takes a `Vec` and fallibly encodes it into a provided external Cobhan Buffer. 281 | /// 282 | /// Will cause an error code if the provided Cobhan Buffer is too small. 283 | /// 284 | /// ## Notes 285 | /// 286 | /// This function does a memcopy from the Rust data into the provided Cobhan Buffer. 287 | /// 288 | /// ## Safety 289 | /// 290 | /// Behavior is undefined if any of the following conditions are violated: 291 | /// - The Cobhan Buffer Header size is not correctly reserved or formatted. 292 | /// - Any of the Safety conditions of [`std::slice::from_raw_parts`][] is violated. 293 | pub unsafe fn bytes_to_cbuffer(bytes: &[u8], buffer: *mut c_char) -> i32 { 294 | if buffer.is_null() { 295 | debug_print!("bytes_to_cbuffer: buffer is NULL"); 296 | return ERR_NULL_PTR; 297 | } 298 | 299 | let length = buffer as *mut i32; 300 | let _reserved = buffer.offset(SIZEOF_INT32) as *mut i32; 301 | let payload = (buffer.offset(BUFFER_HEADER_SIZE)) as *mut u8; 302 | 303 | let buffer_cap = *length; 304 | debug_print!("bytes_to_cbuffer: buffer capacity is {}", buffer_cap); 305 | 306 | if buffer_cap <= 0 { 307 | debug_print!("bytes_to_cbuffer: Invalid buffer capacity"); 308 | return ERR_BUFFER_TOO_SMALL; 309 | } 310 | 311 | let bytes_len = bytes.len(); 312 | debug_print!("bytes_to_cbuffer: bytes.len() is {}", bytes_len); 313 | 314 | if buffer_cap < (bytes_len as i32) { 315 | debug_print!("bytes_to_cbuffer: calling bytes_to_temp"); 316 | return bytes_to_temp(bytes, buffer); 317 | } 318 | 319 | copy_nonoverlapping(bytes.as_ptr(), payload, bytes_len); 320 | 321 | *length = bytes_len as i32; 322 | 323 | ERR_NONE 324 | } 325 | 326 | /// Sets a tempfile data for a payload and writes bytes to it. 327 | unsafe fn bytes_to_temp(bytes: &[u8], buffer: *mut c_char) -> i32 { 328 | // TODO: eventually replace this pattern with if-let once that is stable -jsenkpiel 329 | let tmp_file_path = match write_new_file(bytes) { 330 | Ok(t) => t, 331 | Err(r) => return r, 332 | }; 333 | debug_print!( 334 | "bytes_to_temp: write_new_file wrote {} bytes to {}", 335 | bytes.len(), 336 | tmp_file_path 337 | ); 338 | 339 | let length = buffer as *mut i32; 340 | let tmp_file_path_len = tmp_file_path.len() as i32; 341 | 342 | //NOTE: We explicitly test this so we don't recursively attempt to create temp files with string_to_cbuffer() 343 | if *length < tmp_file_path_len { 344 | //Temp file path won't fit in output buffer, we're out of luck 345 | debug_print!( 346 | "bytes_to_temp: temp file path {} is larger than buffer capacity {}", 347 | tmp_file_path, 348 | *length 349 | ); 350 | let _ = fs::remove_file(tmp_file_path); 351 | return ERR_BUFFER_TOO_SMALL; 352 | } 353 | 354 | let result = string_to_cbuffer(&tmp_file_path, buffer); 355 | if result != ERR_NONE { 356 | debug_print!( 357 | "bytes_to_temp: failed to store temp path {} in buffer", 358 | tmp_file_path 359 | ); 360 | let _ = fs::remove_file(tmp_file_path); 361 | return result; 362 | } 363 | 364 | *length = 0 - tmp_file_path_len; 365 | 366 | result 367 | } 368 | 369 | // Writes to a new named temporary file and returns the file name. 370 | fn write_new_file(bytes: &[u8]) -> Result { 371 | let mut tmpfile = NamedTempFile::new().map_err(|_| ERR_WRITE_TEMP_FILE_FAILED)?; 372 | 373 | if tmpfile.write_all(bytes).is_err() { 374 | return Err(ERR_WRITE_TEMP_FILE_FAILED); 375 | }; 376 | 377 | let (_, path) = tmpfile.keep().map_err(|_| ERR_WRITE_TEMP_FILE_FAILED)?; 378 | 379 | path.into_os_string() 380 | .into_string() 381 | .map_err(|_| ERR_WRITE_TEMP_FILE_FAILED) 382 | } 383 | -------------------------------------------------------------------------------- /libcobhandemo/node-test/consumer-console-app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "consumer-console-app", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "consumer-console-app", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "libcobhandemo": "file:../libcobhandemo", 13 | "process": "^0.11.10" 14 | }, 15 | "devDependencies": { 16 | "eslint": "^7.32.0", 17 | "eslint-config-google": "^0.14.0" 18 | } 19 | }, 20 | "../libcobhandemo": { 21 | "version": "1.2.2", 22 | "license": "ISC", 23 | "dependencies": { 24 | "cobhan": "^1.0.15" 25 | }, 26 | "devDependencies": { 27 | "eslint": "^7.32.0", 28 | "eslint-config-google": "^0.14.0" 29 | } 30 | }, 31 | "node_modules/@babel/code-frame": { 32 | "version": "7.12.11", 33 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", 34 | "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", 35 | "dev": true, 36 | "dependencies": { 37 | "@babel/highlight": "^7.10.4" 38 | } 39 | }, 40 | "node_modules/@babel/helper-validator-identifier": { 41 | "version": "7.16.7", 42 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", 43 | "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", 44 | "dev": true, 45 | "engines": { 46 | "node": ">=6.9.0" 47 | } 48 | }, 49 | "node_modules/@babel/highlight": { 50 | "version": "7.16.10", 51 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", 52 | "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", 53 | "dev": true, 54 | "dependencies": { 55 | "@babel/helper-validator-identifier": "^7.16.7", 56 | "chalk": "^2.0.0", 57 | "js-tokens": "^4.0.0" 58 | }, 59 | "engines": { 60 | "node": ">=6.9.0" 61 | } 62 | }, 63 | "node_modules/@babel/highlight/node_modules/ansi-styles": { 64 | "version": "3.2.1", 65 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 66 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 67 | "dev": true, 68 | "dependencies": { 69 | "color-convert": "^1.9.0" 70 | }, 71 | "engines": { 72 | "node": ">=4" 73 | } 74 | }, 75 | "node_modules/@babel/highlight/node_modules/chalk": { 76 | "version": "2.4.2", 77 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 78 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 79 | "dev": true, 80 | "dependencies": { 81 | "ansi-styles": "^3.2.1", 82 | "escape-string-regexp": "^1.0.5", 83 | "supports-color": "^5.3.0" 84 | }, 85 | "engines": { 86 | "node": ">=4" 87 | } 88 | }, 89 | "node_modules/@babel/highlight/node_modules/color-convert": { 90 | "version": "1.9.3", 91 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 92 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 93 | "dev": true, 94 | "dependencies": { 95 | "color-name": "1.1.3" 96 | } 97 | }, 98 | "node_modules/@babel/highlight/node_modules/color-name": { 99 | "version": "1.1.3", 100 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 101 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 102 | "dev": true 103 | }, 104 | "node_modules/@babel/highlight/node_modules/escape-string-regexp": { 105 | "version": "1.0.5", 106 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 107 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 108 | "dev": true, 109 | "engines": { 110 | "node": ">=0.8.0" 111 | } 112 | }, 113 | "node_modules/@babel/highlight/node_modules/has-flag": { 114 | "version": "3.0.0", 115 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 116 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 117 | "dev": true, 118 | "engines": { 119 | "node": ">=4" 120 | } 121 | }, 122 | "node_modules/@babel/highlight/node_modules/supports-color": { 123 | "version": "5.5.0", 124 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 125 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 126 | "dev": true, 127 | "dependencies": { 128 | "has-flag": "^3.0.0" 129 | }, 130 | "engines": { 131 | "node": ">=4" 132 | } 133 | }, 134 | "node_modules/@eslint/eslintrc": { 135 | "version": "0.4.3", 136 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", 137 | "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", 138 | "dev": true, 139 | "dependencies": { 140 | "ajv": "^6.12.4", 141 | "debug": "^4.1.1", 142 | "espree": "^7.3.0", 143 | "globals": "^13.9.0", 144 | "ignore": "^4.0.6", 145 | "import-fresh": "^3.2.1", 146 | "js-yaml": "^3.13.1", 147 | "minimatch": "^3.0.4", 148 | "strip-json-comments": "^3.1.1" 149 | }, 150 | "engines": { 151 | "node": "^10.12.0 || >=12.0.0" 152 | } 153 | }, 154 | "node_modules/@humanwhocodes/config-array": { 155 | "version": "0.5.0", 156 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", 157 | "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", 158 | "dev": true, 159 | "dependencies": { 160 | "@humanwhocodes/object-schema": "^1.2.0", 161 | "debug": "^4.1.1", 162 | "minimatch": "^3.0.4" 163 | }, 164 | "engines": { 165 | "node": ">=10.10.0" 166 | } 167 | }, 168 | "node_modules/@humanwhocodes/object-schema": { 169 | "version": "1.2.1", 170 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 171 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 172 | "dev": true 173 | }, 174 | "node_modules/acorn": { 175 | "version": "7.4.1", 176 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 177 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 178 | "dev": true, 179 | "bin": { 180 | "acorn": "bin/acorn" 181 | }, 182 | "engines": { 183 | "node": ">=0.4.0" 184 | } 185 | }, 186 | "node_modules/acorn-jsx": { 187 | "version": "5.3.2", 188 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 189 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 190 | "dev": true, 191 | "peerDependencies": { 192 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 193 | } 194 | }, 195 | "node_modules/ajv": { 196 | "version": "6.12.6", 197 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 198 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 199 | "dev": true, 200 | "dependencies": { 201 | "fast-deep-equal": "^3.1.1", 202 | "fast-json-stable-stringify": "^2.0.0", 203 | "json-schema-traverse": "^0.4.1", 204 | "uri-js": "^4.2.2" 205 | }, 206 | "funding": { 207 | "type": "github", 208 | "url": "https://github.com/sponsors/epoberezkin" 209 | } 210 | }, 211 | "node_modules/ansi-colors": { 212 | "version": "4.1.1", 213 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 214 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 215 | "dev": true, 216 | "engines": { 217 | "node": ">=6" 218 | } 219 | }, 220 | "node_modules/ansi-regex": { 221 | "version": "5.0.1", 222 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 223 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 224 | "dev": true, 225 | "engines": { 226 | "node": ">=8" 227 | } 228 | }, 229 | "node_modules/ansi-styles": { 230 | "version": "4.3.0", 231 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 232 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 233 | "dev": true, 234 | "dependencies": { 235 | "color-convert": "^2.0.1" 236 | }, 237 | "engines": { 238 | "node": ">=8" 239 | }, 240 | "funding": { 241 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 242 | } 243 | }, 244 | "node_modules/argparse": { 245 | "version": "1.0.10", 246 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 247 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 248 | "dev": true, 249 | "dependencies": { 250 | "sprintf-js": "~1.0.2" 251 | } 252 | }, 253 | "node_modules/astral-regex": { 254 | "version": "2.0.0", 255 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 256 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", 257 | "dev": true, 258 | "engines": { 259 | "node": ">=8" 260 | } 261 | }, 262 | "node_modules/balanced-match": { 263 | "version": "1.0.2", 264 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 265 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 266 | "dev": true 267 | }, 268 | "node_modules/brace-expansion": { 269 | "version": "1.1.11", 270 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 271 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 272 | "dev": true, 273 | "dependencies": { 274 | "balanced-match": "^1.0.0", 275 | "concat-map": "0.0.1" 276 | } 277 | }, 278 | "node_modules/callsites": { 279 | "version": "3.1.0", 280 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 281 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 282 | "dev": true, 283 | "engines": { 284 | "node": ">=6" 285 | } 286 | }, 287 | "node_modules/chalk": { 288 | "version": "4.1.2", 289 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 290 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 291 | "dev": true, 292 | "dependencies": { 293 | "ansi-styles": "^4.1.0", 294 | "supports-color": "^7.1.0" 295 | }, 296 | "engines": { 297 | "node": ">=10" 298 | }, 299 | "funding": { 300 | "url": "https://github.com/chalk/chalk?sponsor=1" 301 | } 302 | }, 303 | "node_modules/color-convert": { 304 | "version": "2.0.1", 305 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 306 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 307 | "dev": true, 308 | "dependencies": { 309 | "color-name": "~1.1.4" 310 | }, 311 | "engines": { 312 | "node": ">=7.0.0" 313 | } 314 | }, 315 | "node_modules/color-name": { 316 | "version": "1.1.4", 317 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 318 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 319 | "dev": true 320 | }, 321 | "node_modules/concat-map": { 322 | "version": "0.0.1", 323 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 324 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 325 | "dev": true 326 | }, 327 | "node_modules/cross-spawn": { 328 | "version": "7.0.3", 329 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 330 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 331 | "dev": true, 332 | "dependencies": { 333 | "path-key": "^3.1.0", 334 | "shebang-command": "^2.0.0", 335 | "which": "^2.0.1" 336 | }, 337 | "engines": { 338 | "node": ">= 8" 339 | } 340 | }, 341 | "node_modules/debug": { 342 | "version": "4.3.3", 343 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 344 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 345 | "dev": true, 346 | "dependencies": { 347 | "ms": "2.1.2" 348 | }, 349 | "engines": { 350 | "node": ">=6.0" 351 | }, 352 | "peerDependenciesMeta": { 353 | "supports-color": { 354 | "optional": true 355 | } 356 | } 357 | }, 358 | "node_modules/deep-is": { 359 | "version": "0.1.4", 360 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 361 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 362 | "dev": true 363 | }, 364 | "node_modules/doctrine": { 365 | "version": "3.0.0", 366 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 367 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 368 | "dev": true, 369 | "dependencies": { 370 | "esutils": "^2.0.2" 371 | }, 372 | "engines": { 373 | "node": ">=6.0.0" 374 | } 375 | }, 376 | "node_modules/emoji-regex": { 377 | "version": "8.0.0", 378 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 379 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 380 | "dev": true 381 | }, 382 | "node_modules/enquirer": { 383 | "version": "2.3.6", 384 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 385 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 386 | "dev": true, 387 | "dependencies": { 388 | "ansi-colors": "^4.1.1" 389 | }, 390 | "engines": { 391 | "node": ">=8.6" 392 | } 393 | }, 394 | "node_modules/escape-string-regexp": { 395 | "version": "4.0.0", 396 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 397 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 398 | "dev": true, 399 | "engines": { 400 | "node": ">=10" 401 | }, 402 | "funding": { 403 | "url": "https://github.com/sponsors/sindresorhus" 404 | } 405 | }, 406 | "node_modules/eslint": { 407 | "version": "7.32.0", 408 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", 409 | "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", 410 | "dev": true, 411 | "dependencies": { 412 | "@babel/code-frame": "7.12.11", 413 | "@eslint/eslintrc": "^0.4.3", 414 | "@humanwhocodes/config-array": "^0.5.0", 415 | "ajv": "^6.10.0", 416 | "chalk": "^4.0.0", 417 | "cross-spawn": "^7.0.2", 418 | "debug": "^4.0.1", 419 | "doctrine": "^3.0.0", 420 | "enquirer": "^2.3.5", 421 | "escape-string-regexp": "^4.0.0", 422 | "eslint-scope": "^5.1.1", 423 | "eslint-utils": "^2.1.0", 424 | "eslint-visitor-keys": "^2.0.0", 425 | "espree": "^7.3.1", 426 | "esquery": "^1.4.0", 427 | "esutils": "^2.0.2", 428 | "fast-deep-equal": "^3.1.3", 429 | "file-entry-cache": "^6.0.1", 430 | "functional-red-black-tree": "^1.0.1", 431 | "glob-parent": "^5.1.2", 432 | "globals": "^13.6.0", 433 | "ignore": "^4.0.6", 434 | "import-fresh": "^3.0.0", 435 | "imurmurhash": "^0.1.4", 436 | "is-glob": "^4.0.0", 437 | "js-yaml": "^3.13.1", 438 | "json-stable-stringify-without-jsonify": "^1.0.1", 439 | "levn": "^0.4.1", 440 | "lodash.merge": "^4.6.2", 441 | "minimatch": "^3.0.4", 442 | "natural-compare": "^1.4.0", 443 | "optionator": "^0.9.1", 444 | "progress": "^2.0.0", 445 | "regexpp": "^3.1.0", 446 | "semver": "^7.2.1", 447 | "strip-ansi": "^6.0.0", 448 | "strip-json-comments": "^3.1.0", 449 | "table": "^6.0.9", 450 | "text-table": "^0.2.0", 451 | "v8-compile-cache": "^2.0.3" 452 | }, 453 | "bin": { 454 | "eslint": "bin/eslint.js" 455 | }, 456 | "engines": { 457 | "node": "^10.12.0 || >=12.0.0" 458 | }, 459 | "funding": { 460 | "url": "https://opencollective.com/eslint" 461 | } 462 | }, 463 | "node_modules/eslint-config-google": { 464 | "version": "0.14.0", 465 | "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", 466 | "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", 467 | "dev": true, 468 | "engines": { 469 | "node": ">=0.10.0" 470 | }, 471 | "peerDependencies": { 472 | "eslint": ">=5.16.0" 473 | } 474 | }, 475 | "node_modules/eslint-scope": { 476 | "version": "5.1.1", 477 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 478 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 479 | "dev": true, 480 | "dependencies": { 481 | "esrecurse": "^4.3.0", 482 | "estraverse": "^4.1.1" 483 | }, 484 | "engines": { 485 | "node": ">=8.0.0" 486 | } 487 | }, 488 | "node_modules/eslint-utils": { 489 | "version": "2.1.0", 490 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 491 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 492 | "dev": true, 493 | "dependencies": { 494 | "eslint-visitor-keys": "^1.1.0" 495 | }, 496 | "engines": { 497 | "node": ">=6" 498 | }, 499 | "funding": { 500 | "url": "https://github.com/sponsors/mysticatea" 501 | } 502 | }, 503 | "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { 504 | "version": "1.3.0", 505 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 506 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 507 | "dev": true, 508 | "engines": { 509 | "node": ">=4" 510 | } 511 | }, 512 | "node_modules/eslint-visitor-keys": { 513 | "version": "2.1.0", 514 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 515 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 516 | "dev": true, 517 | "engines": { 518 | "node": ">=10" 519 | } 520 | }, 521 | "node_modules/espree": { 522 | "version": "7.3.1", 523 | "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", 524 | "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", 525 | "dev": true, 526 | "dependencies": { 527 | "acorn": "^7.4.0", 528 | "acorn-jsx": "^5.3.1", 529 | "eslint-visitor-keys": "^1.3.0" 530 | }, 531 | "engines": { 532 | "node": "^10.12.0 || >=12.0.0" 533 | } 534 | }, 535 | "node_modules/espree/node_modules/eslint-visitor-keys": { 536 | "version": "1.3.0", 537 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 538 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 539 | "dev": true, 540 | "engines": { 541 | "node": ">=4" 542 | } 543 | }, 544 | "node_modules/esprima": { 545 | "version": "4.0.1", 546 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 547 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 548 | "dev": true, 549 | "bin": { 550 | "esparse": "bin/esparse.js", 551 | "esvalidate": "bin/esvalidate.js" 552 | }, 553 | "engines": { 554 | "node": ">=4" 555 | } 556 | }, 557 | "node_modules/esquery": { 558 | "version": "1.4.0", 559 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 560 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 561 | "dev": true, 562 | "dependencies": { 563 | "estraverse": "^5.1.0" 564 | }, 565 | "engines": { 566 | "node": ">=0.10" 567 | } 568 | }, 569 | "node_modules/esquery/node_modules/estraverse": { 570 | "version": "5.3.0", 571 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 572 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 573 | "dev": true, 574 | "engines": { 575 | "node": ">=4.0" 576 | } 577 | }, 578 | "node_modules/esrecurse": { 579 | "version": "4.3.0", 580 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 581 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 582 | "dev": true, 583 | "dependencies": { 584 | "estraverse": "^5.2.0" 585 | }, 586 | "engines": { 587 | "node": ">=4.0" 588 | } 589 | }, 590 | "node_modules/esrecurse/node_modules/estraverse": { 591 | "version": "5.3.0", 592 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 593 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 594 | "dev": true, 595 | "engines": { 596 | "node": ">=4.0" 597 | } 598 | }, 599 | "node_modules/estraverse": { 600 | "version": "4.3.0", 601 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 602 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 603 | "dev": true, 604 | "engines": { 605 | "node": ">=4.0" 606 | } 607 | }, 608 | "node_modules/esutils": { 609 | "version": "2.0.3", 610 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 611 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 612 | "dev": true, 613 | "engines": { 614 | "node": ">=0.10.0" 615 | } 616 | }, 617 | "node_modules/fast-deep-equal": { 618 | "version": "3.1.3", 619 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 620 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 621 | "dev": true 622 | }, 623 | "node_modules/fast-json-stable-stringify": { 624 | "version": "2.1.0", 625 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 626 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 627 | "dev": true 628 | }, 629 | "node_modules/fast-levenshtein": { 630 | "version": "2.0.6", 631 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 632 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 633 | "dev": true 634 | }, 635 | "node_modules/file-entry-cache": { 636 | "version": "6.0.1", 637 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 638 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 639 | "dev": true, 640 | "dependencies": { 641 | "flat-cache": "^3.0.4" 642 | }, 643 | "engines": { 644 | "node": "^10.12.0 || >=12.0.0" 645 | } 646 | }, 647 | "node_modules/flat-cache": { 648 | "version": "3.0.4", 649 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 650 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 651 | "dev": true, 652 | "dependencies": { 653 | "flatted": "^3.1.0", 654 | "rimraf": "^3.0.2" 655 | }, 656 | "engines": { 657 | "node": "^10.12.0 || >=12.0.0" 658 | } 659 | }, 660 | "node_modules/flatted": { 661 | "version": "3.2.5", 662 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", 663 | "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", 664 | "dev": true 665 | }, 666 | "node_modules/fs.realpath": { 667 | "version": "1.0.0", 668 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 669 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 670 | "dev": true 671 | }, 672 | "node_modules/functional-red-black-tree": { 673 | "version": "1.0.1", 674 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 675 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 676 | "dev": true 677 | }, 678 | "node_modules/glob": { 679 | "version": "7.2.0", 680 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 681 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 682 | "dev": true, 683 | "dependencies": { 684 | "fs.realpath": "^1.0.0", 685 | "inflight": "^1.0.4", 686 | "inherits": "2", 687 | "minimatch": "^3.0.4", 688 | "once": "^1.3.0", 689 | "path-is-absolute": "^1.0.0" 690 | }, 691 | "engines": { 692 | "node": "*" 693 | }, 694 | "funding": { 695 | "url": "https://github.com/sponsors/isaacs" 696 | } 697 | }, 698 | "node_modules/glob-parent": { 699 | "version": "5.1.2", 700 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 701 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 702 | "dev": true, 703 | "dependencies": { 704 | "is-glob": "^4.0.1" 705 | }, 706 | "engines": { 707 | "node": ">= 6" 708 | } 709 | }, 710 | "node_modules/globals": { 711 | "version": "13.12.1", 712 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", 713 | "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", 714 | "dev": true, 715 | "dependencies": { 716 | "type-fest": "^0.20.2" 717 | }, 718 | "engines": { 719 | "node": ">=8" 720 | }, 721 | "funding": { 722 | "url": "https://github.com/sponsors/sindresorhus" 723 | } 724 | }, 725 | "node_modules/has-flag": { 726 | "version": "4.0.0", 727 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 728 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 729 | "dev": true, 730 | "engines": { 731 | "node": ">=8" 732 | } 733 | }, 734 | "node_modules/ignore": { 735 | "version": "4.0.6", 736 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 737 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 738 | "dev": true, 739 | "engines": { 740 | "node": ">= 4" 741 | } 742 | }, 743 | "node_modules/import-fresh": { 744 | "version": "3.3.0", 745 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 746 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 747 | "dev": true, 748 | "dependencies": { 749 | "parent-module": "^1.0.0", 750 | "resolve-from": "^4.0.0" 751 | }, 752 | "engines": { 753 | "node": ">=6" 754 | }, 755 | "funding": { 756 | "url": "https://github.com/sponsors/sindresorhus" 757 | } 758 | }, 759 | "node_modules/imurmurhash": { 760 | "version": "0.1.4", 761 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 762 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 763 | "dev": true, 764 | "engines": { 765 | "node": ">=0.8.19" 766 | } 767 | }, 768 | "node_modules/inflight": { 769 | "version": "1.0.6", 770 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 771 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 772 | "dev": true, 773 | "dependencies": { 774 | "once": "^1.3.0", 775 | "wrappy": "1" 776 | } 777 | }, 778 | "node_modules/inherits": { 779 | "version": "2.0.4", 780 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 781 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 782 | "dev": true 783 | }, 784 | "node_modules/is-extglob": { 785 | "version": "2.1.1", 786 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 787 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 788 | "dev": true, 789 | "engines": { 790 | "node": ">=0.10.0" 791 | } 792 | }, 793 | "node_modules/is-fullwidth-code-point": { 794 | "version": "3.0.0", 795 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 796 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 797 | "dev": true, 798 | "engines": { 799 | "node": ">=8" 800 | } 801 | }, 802 | "node_modules/is-glob": { 803 | "version": "4.0.3", 804 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 805 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 806 | "dev": true, 807 | "dependencies": { 808 | "is-extglob": "^2.1.1" 809 | }, 810 | "engines": { 811 | "node": ">=0.10.0" 812 | } 813 | }, 814 | "node_modules/isexe": { 815 | "version": "2.0.0", 816 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 817 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 818 | "dev": true 819 | }, 820 | "node_modules/js-tokens": { 821 | "version": "4.0.0", 822 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 823 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 824 | "dev": true 825 | }, 826 | "node_modules/js-yaml": { 827 | "version": "3.14.1", 828 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 829 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 830 | "dev": true, 831 | "dependencies": { 832 | "argparse": "^1.0.7", 833 | "esprima": "^4.0.0" 834 | }, 835 | "bin": { 836 | "js-yaml": "bin/js-yaml.js" 837 | } 838 | }, 839 | "node_modules/json-schema-traverse": { 840 | "version": "0.4.1", 841 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 842 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 843 | "dev": true 844 | }, 845 | "node_modules/json-stable-stringify-without-jsonify": { 846 | "version": "1.0.1", 847 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 848 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 849 | "dev": true 850 | }, 851 | "node_modules/levn": { 852 | "version": "0.4.1", 853 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 854 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 855 | "dev": true, 856 | "dependencies": { 857 | "prelude-ls": "^1.2.1", 858 | "type-check": "~0.4.0" 859 | }, 860 | "engines": { 861 | "node": ">= 0.8.0" 862 | } 863 | }, 864 | "node_modules/libcobhandemo": { 865 | "resolved": "../libcobhandemo", 866 | "link": true 867 | }, 868 | "node_modules/lodash.merge": { 869 | "version": "4.6.2", 870 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 871 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 872 | "dev": true 873 | }, 874 | "node_modules/lodash.truncate": { 875 | "version": "4.4.2", 876 | "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", 877 | "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", 878 | "dev": true 879 | }, 880 | "node_modules/lru-cache": { 881 | "version": "6.0.0", 882 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 883 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 884 | "dev": true, 885 | "dependencies": { 886 | "yallist": "^4.0.0" 887 | }, 888 | "engines": { 889 | "node": ">=10" 890 | } 891 | }, 892 | "node_modules/minimatch": { 893 | "version": "3.1.2", 894 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 895 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 896 | "dev": true, 897 | "dependencies": { 898 | "brace-expansion": "^1.1.7" 899 | }, 900 | "engines": { 901 | "node": "*" 902 | } 903 | }, 904 | "node_modules/ms": { 905 | "version": "2.1.2", 906 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 907 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 908 | "dev": true 909 | }, 910 | "node_modules/natural-compare": { 911 | "version": "1.4.0", 912 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 913 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 914 | "dev": true 915 | }, 916 | "node_modules/once": { 917 | "version": "1.4.0", 918 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 919 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 920 | "dev": true, 921 | "dependencies": { 922 | "wrappy": "1" 923 | } 924 | }, 925 | "node_modules/optionator": { 926 | "version": "0.9.1", 927 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 928 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 929 | "dev": true, 930 | "dependencies": { 931 | "deep-is": "^0.1.3", 932 | "fast-levenshtein": "^2.0.6", 933 | "levn": "^0.4.1", 934 | "prelude-ls": "^1.2.1", 935 | "type-check": "^0.4.0", 936 | "word-wrap": "^1.2.3" 937 | }, 938 | "engines": { 939 | "node": ">= 0.8.0" 940 | } 941 | }, 942 | "node_modules/parent-module": { 943 | "version": "1.0.1", 944 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 945 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 946 | "dev": true, 947 | "dependencies": { 948 | "callsites": "^3.0.0" 949 | }, 950 | "engines": { 951 | "node": ">=6" 952 | } 953 | }, 954 | "node_modules/path-is-absolute": { 955 | "version": "1.0.1", 956 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 957 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 958 | "dev": true, 959 | "engines": { 960 | "node": ">=0.10.0" 961 | } 962 | }, 963 | "node_modules/path-key": { 964 | "version": "3.1.1", 965 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 966 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 967 | "dev": true, 968 | "engines": { 969 | "node": ">=8" 970 | } 971 | }, 972 | "node_modules/prelude-ls": { 973 | "version": "1.2.1", 974 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 975 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 976 | "dev": true, 977 | "engines": { 978 | "node": ">= 0.8.0" 979 | } 980 | }, 981 | "node_modules/process": { 982 | "version": "0.11.10", 983 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 984 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", 985 | "engines": { 986 | "node": ">= 0.6.0" 987 | } 988 | }, 989 | "node_modules/progress": { 990 | "version": "2.0.3", 991 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 992 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 993 | "dev": true, 994 | "engines": { 995 | "node": ">=0.4.0" 996 | } 997 | }, 998 | "node_modules/punycode": { 999 | "version": "2.1.1", 1000 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1001 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1002 | "dev": true, 1003 | "engines": { 1004 | "node": ">=6" 1005 | } 1006 | }, 1007 | "node_modules/regexpp": { 1008 | "version": "3.2.0", 1009 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 1010 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 1011 | "dev": true, 1012 | "engines": { 1013 | "node": ">=8" 1014 | }, 1015 | "funding": { 1016 | "url": "https://github.com/sponsors/mysticatea" 1017 | } 1018 | }, 1019 | "node_modules/require-from-string": { 1020 | "version": "2.0.2", 1021 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 1022 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 1023 | "dev": true, 1024 | "engines": { 1025 | "node": ">=0.10.0" 1026 | } 1027 | }, 1028 | "node_modules/resolve-from": { 1029 | "version": "4.0.0", 1030 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1031 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1032 | "dev": true, 1033 | "engines": { 1034 | "node": ">=4" 1035 | } 1036 | }, 1037 | "node_modules/rimraf": { 1038 | "version": "3.0.2", 1039 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1040 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1041 | "dev": true, 1042 | "dependencies": { 1043 | "glob": "^7.1.3" 1044 | }, 1045 | "bin": { 1046 | "rimraf": "bin.js" 1047 | }, 1048 | "funding": { 1049 | "url": "https://github.com/sponsors/isaacs" 1050 | } 1051 | }, 1052 | "node_modules/semver": { 1053 | "version": "7.3.5", 1054 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 1055 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 1056 | "dev": true, 1057 | "dependencies": { 1058 | "lru-cache": "^6.0.0" 1059 | }, 1060 | "bin": { 1061 | "semver": "bin/semver.js" 1062 | }, 1063 | "engines": { 1064 | "node": ">=10" 1065 | } 1066 | }, 1067 | "node_modules/shebang-command": { 1068 | "version": "2.0.0", 1069 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1070 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1071 | "dev": true, 1072 | "dependencies": { 1073 | "shebang-regex": "^3.0.0" 1074 | }, 1075 | "engines": { 1076 | "node": ">=8" 1077 | } 1078 | }, 1079 | "node_modules/shebang-regex": { 1080 | "version": "3.0.0", 1081 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1082 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1083 | "dev": true, 1084 | "engines": { 1085 | "node": ">=8" 1086 | } 1087 | }, 1088 | "node_modules/slice-ansi": { 1089 | "version": "4.0.0", 1090 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", 1091 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", 1092 | "dev": true, 1093 | "dependencies": { 1094 | "ansi-styles": "^4.0.0", 1095 | "astral-regex": "^2.0.0", 1096 | "is-fullwidth-code-point": "^3.0.0" 1097 | }, 1098 | "engines": { 1099 | "node": ">=10" 1100 | }, 1101 | "funding": { 1102 | "url": "https://github.com/chalk/slice-ansi?sponsor=1" 1103 | } 1104 | }, 1105 | "node_modules/sprintf-js": { 1106 | "version": "1.0.3", 1107 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1108 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1109 | "dev": true 1110 | }, 1111 | "node_modules/string-width": { 1112 | "version": "4.2.3", 1113 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1114 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1115 | "dev": true, 1116 | "dependencies": { 1117 | "emoji-regex": "^8.0.0", 1118 | "is-fullwidth-code-point": "^3.0.0", 1119 | "strip-ansi": "^6.0.1" 1120 | }, 1121 | "engines": { 1122 | "node": ">=8" 1123 | } 1124 | }, 1125 | "node_modules/strip-ansi": { 1126 | "version": "6.0.1", 1127 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1128 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1129 | "dev": true, 1130 | "dependencies": { 1131 | "ansi-regex": "^5.0.1" 1132 | }, 1133 | "engines": { 1134 | "node": ">=8" 1135 | } 1136 | }, 1137 | "node_modules/strip-json-comments": { 1138 | "version": "3.1.1", 1139 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1140 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1141 | "dev": true, 1142 | "engines": { 1143 | "node": ">=8" 1144 | }, 1145 | "funding": { 1146 | "url": "https://github.com/sponsors/sindresorhus" 1147 | } 1148 | }, 1149 | "node_modules/supports-color": { 1150 | "version": "7.2.0", 1151 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1152 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1153 | "dev": true, 1154 | "dependencies": { 1155 | "has-flag": "^4.0.0" 1156 | }, 1157 | "engines": { 1158 | "node": ">=8" 1159 | } 1160 | }, 1161 | "node_modules/table": { 1162 | "version": "6.8.0", 1163 | "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", 1164 | "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", 1165 | "dev": true, 1166 | "dependencies": { 1167 | "ajv": "^8.0.1", 1168 | "lodash.truncate": "^4.4.2", 1169 | "slice-ansi": "^4.0.0", 1170 | "string-width": "^4.2.3", 1171 | "strip-ansi": "^6.0.1" 1172 | }, 1173 | "engines": { 1174 | "node": ">=10.0.0" 1175 | } 1176 | }, 1177 | "node_modules/table/node_modules/ajv": { 1178 | "version": "8.10.0", 1179 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", 1180 | "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", 1181 | "dev": true, 1182 | "dependencies": { 1183 | "fast-deep-equal": "^3.1.1", 1184 | "json-schema-traverse": "^1.0.0", 1185 | "require-from-string": "^2.0.2", 1186 | "uri-js": "^4.2.2" 1187 | }, 1188 | "funding": { 1189 | "type": "github", 1190 | "url": "https://github.com/sponsors/epoberezkin" 1191 | } 1192 | }, 1193 | "node_modules/table/node_modules/json-schema-traverse": { 1194 | "version": "1.0.0", 1195 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", 1196 | "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", 1197 | "dev": true 1198 | }, 1199 | "node_modules/text-table": { 1200 | "version": "0.2.0", 1201 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1202 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1203 | "dev": true 1204 | }, 1205 | "node_modules/type-check": { 1206 | "version": "0.4.0", 1207 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1208 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1209 | "dev": true, 1210 | "dependencies": { 1211 | "prelude-ls": "^1.2.1" 1212 | }, 1213 | "engines": { 1214 | "node": ">= 0.8.0" 1215 | } 1216 | }, 1217 | "node_modules/type-fest": { 1218 | "version": "0.20.2", 1219 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 1220 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 1221 | "dev": true, 1222 | "engines": { 1223 | "node": ">=10" 1224 | }, 1225 | "funding": { 1226 | "url": "https://github.com/sponsors/sindresorhus" 1227 | } 1228 | }, 1229 | "node_modules/uri-js": { 1230 | "version": "4.4.1", 1231 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1232 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1233 | "dev": true, 1234 | "dependencies": { 1235 | "punycode": "^2.1.0" 1236 | } 1237 | }, 1238 | "node_modules/v8-compile-cache": { 1239 | "version": "2.3.0", 1240 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 1241 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 1242 | "dev": true 1243 | }, 1244 | "node_modules/which": { 1245 | "version": "2.0.2", 1246 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1247 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1248 | "dev": true, 1249 | "dependencies": { 1250 | "isexe": "^2.0.0" 1251 | }, 1252 | "bin": { 1253 | "node-which": "bin/node-which" 1254 | }, 1255 | "engines": { 1256 | "node": ">= 8" 1257 | } 1258 | }, 1259 | "node_modules/word-wrap": { 1260 | "version": "1.2.3", 1261 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1262 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1263 | "dev": true, 1264 | "engines": { 1265 | "node": ">=0.10.0" 1266 | } 1267 | }, 1268 | "node_modules/wrappy": { 1269 | "version": "1.0.2", 1270 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1271 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1272 | "dev": true 1273 | }, 1274 | "node_modules/yallist": { 1275 | "version": "4.0.0", 1276 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1277 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 1278 | "dev": true 1279 | } 1280 | }, 1281 | "dependencies": { 1282 | "@babel/code-frame": { 1283 | "version": "7.12.11", 1284 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", 1285 | "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", 1286 | "dev": true, 1287 | "requires": { 1288 | "@babel/highlight": "^7.10.4" 1289 | } 1290 | }, 1291 | "@babel/helper-validator-identifier": { 1292 | "version": "7.16.7", 1293 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", 1294 | "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", 1295 | "dev": true 1296 | }, 1297 | "@babel/highlight": { 1298 | "version": "7.16.10", 1299 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", 1300 | "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", 1301 | "dev": true, 1302 | "requires": { 1303 | "@babel/helper-validator-identifier": "^7.16.7", 1304 | "chalk": "^2.0.0", 1305 | "js-tokens": "^4.0.0" 1306 | }, 1307 | "dependencies": { 1308 | "ansi-styles": { 1309 | "version": "3.2.1", 1310 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 1311 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 1312 | "dev": true, 1313 | "requires": { 1314 | "color-convert": "^1.9.0" 1315 | } 1316 | }, 1317 | "chalk": { 1318 | "version": "2.4.2", 1319 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 1320 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 1321 | "dev": true, 1322 | "requires": { 1323 | "ansi-styles": "^3.2.1", 1324 | "escape-string-regexp": "^1.0.5", 1325 | "supports-color": "^5.3.0" 1326 | } 1327 | }, 1328 | "color-convert": { 1329 | "version": "1.9.3", 1330 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 1331 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 1332 | "dev": true, 1333 | "requires": { 1334 | "color-name": "1.1.3" 1335 | } 1336 | }, 1337 | "color-name": { 1338 | "version": "1.1.3", 1339 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 1340 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 1341 | "dev": true 1342 | }, 1343 | "escape-string-regexp": { 1344 | "version": "1.0.5", 1345 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 1346 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 1347 | "dev": true 1348 | }, 1349 | "has-flag": { 1350 | "version": "3.0.0", 1351 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1352 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 1353 | "dev": true 1354 | }, 1355 | "supports-color": { 1356 | "version": "5.5.0", 1357 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1358 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1359 | "dev": true, 1360 | "requires": { 1361 | "has-flag": "^3.0.0" 1362 | } 1363 | } 1364 | } 1365 | }, 1366 | "@eslint/eslintrc": { 1367 | "version": "0.4.3", 1368 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", 1369 | "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", 1370 | "dev": true, 1371 | "requires": { 1372 | "ajv": "^6.12.4", 1373 | "debug": "^4.1.1", 1374 | "espree": "^7.3.0", 1375 | "globals": "^13.9.0", 1376 | "ignore": "^4.0.6", 1377 | "import-fresh": "^3.2.1", 1378 | "js-yaml": "^3.13.1", 1379 | "minimatch": "^3.0.4", 1380 | "strip-json-comments": "^3.1.1" 1381 | } 1382 | }, 1383 | "@humanwhocodes/config-array": { 1384 | "version": "0.5.0", 1385 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", 1386 | "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", 1387 | "dev": true, 1388 | "requires": { 1389 | "@humanwhocodes/object-schema": "^1.2.0", 1390 | "debug": "^4.1.1", 1391 | "minimatch": "^3.0.4" 1392 | } 1393 | }, 1394 | "@humanwhocodes/object-schema": { 1395 | "version": "1.2.1", 1396 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 1397 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 1398 | "dev": true 1399 | }, 1400 | "acorn": { 1401 | "version": "7.4.1", 1402 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 1403 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 1404 | "dev": true 1405 | }, 1406 | "acorn-jsx": { 1407 | "version": "5.3.2", 1408 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 1409 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 1410 | "dev": true, 1411 | "requires": {} 1412 | }, 1413 | "ajv": { 1414 | "version": "6.12.6", 1415 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 1416 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 1417 | "dev": true, 1418 | "requires": { 1419 | "fast-deep-equal": "^3.1.1", 1420 | "fast-json-stable-stringify": "^2.0.0", 1421 | "json-schema-traverse": "^0.4.1", 1422 | "uri-js": "^4.2.2" 1423 | } 1424 | }, 1425 | "ansi-colors": { 1426 | "version": "4.1.1", 1427 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 1428 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 1429 | "dev": true 1430 | }, 1431 | "ansi-regex": { 1432 | "version": "5.0.1", 1433 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1434 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1435 | "dev": true 1436 | }, 1437 | "ansi-styles": { 1438 | "version": "4.3.0", 1439 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1440 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1441 | "dev": true, 1442 | "requires": { 1443 | "color-convert": "^2.0.1" 1444 | } 1445 | }, 1446 | "argparse": { 1447 | "version": "1.0.10", 1448 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 1449 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 1450 | "dev": true, 1451 | "requires": { 1452 | "sprintf-js": "~1.0.2" 1453 | } 1454 | }, 1455 | "astral-regex": { 1456 | "version": "2.0.0", 1457 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 1458 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", 1459 | "dev": true 1460 | }, 1461 | "balanced-match": { 1462 | "version": "1.0.2", 1463 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1464 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1465 | "dev": true 1466 | }, 1467 | "brace-expansion": { 1468 | "version": "1.1.11", 1469 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1470 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1471 | "dev": true, 1472 | "requires": { 1473 | "balanced-match": "^1.0.0", 1474 | "concat-map": "0.0.1" 1475 | } 1476 | }, 1477 | "callsites": { 1478 | "version": "3.1.0", 1479 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 1480 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 1481 | "dev": true 1482 | }, 1483 | "chalk": { 1484 | "version": "4.1.2", 1485 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1486 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1487 | "dev": true, 1488 | "requires": { 1489 | "ansi-styles": "^4.1.0", 1490 | "supports-color": "^7.1.0" 1491 | } 1492 | }, 1493 | "color-convert": { 1494 | "version": "2.0.1", 1495 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1496 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1497 | "dev": true, 1498 | "requires": { 1499 | "color-name": "~1.1.4" 1500 | } 1501 | }, 1502 | "color-name": { 1503 | "version": "1.1.4", 1504 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1505 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1506 | "dev": true 1507 | }, 1508 | "concat-map": { 1509 | "version": "0.0.1", 1510 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1511 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 1512 | "dev": true 1513 | }, 1514 | "cross-spawn": { 1515 | "version": "7.0.3", 1516 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 1517 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 1518 | "dev": true, 1519 | "requires": { 1520 | "path-key": "^3.1.0", 1521 | "shebang-command": "^2.0.0", 1522 | "which": "^2.0.1" 1523 | } 1524 | }, 1525 | "debug": { 1526 | "version": "4.3.3", 1527 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 1528 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 1529 | "dev": true, 1530 | "requires": { 1531 | "ms": "2.1.2" 1532 | } 1533 | }, 1534 | "deep-is": { 1535 | "version": "0.1.4", 1536 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 1537 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 1538 | "dev": true 1539 | }, 1540 | "doctrine": { 1541 | "version": "3.0.0", 1542 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 1543 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 1544 | "dev": true, 1545 | "requires": { 1546 | "esutils": "^2.0.2" 1547 | } 1548 | }, 1549 | "emoji-regex": { 1550 | "version": "8.0.0", 1551 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1552 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1553 | "dev": true 1554 | }, 1555 | "enquirer": { 1556 | "version": "2.3.6", 1557 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 1558 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 1559 | "dev": true, 1560 | "requires": { 1561 | "ansi-colors": "^4.1.1" 1562 | } 1563 | }, 1564 | "escape-string-regexp": { 1565 | "version": "4.0.0", 1566 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1567 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1568 | "dev": true 1569 | }, 1570 | "eslint": { 1571 | "version": "7.32.0", 1572 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", 1573 | "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", 1574 | "dev": true, 1575 | "requires": { 1576 | "@babel/code-frame": "7.12.11", 1577 | "@eslint/eslintrc": "^0.4.3", 1578 | "@humanwhocodes/config-array": "^0.5.0", 1579 | "ajv": "^6.10.0", 1580 | "chalk": "^4.0.0", 1581 | "cross-spawn": "^7.0.2", 1582 | "debug": "^4.0.1", 1583 | "doctrine": "^3.0.0", 1584 | "enquirer": "^2.3.5", 1585 | "escape-string-regexp": "^4.0.0", 1586 | "eslint-scope": "^5.1.1", 1587 | "eslint-utils": "^2.1.0", 1588 | "eslint-visitor-keys": "^2.0.0", 1589 | "espree": "^7.3.1", 1590 | "esquery": "^1.4.0", 1591 | "esutils": "^2.0.2", 1592 | "fast-deep-equal": "^3.1.3", 1593 | "file-entry-cache": "^6.0.1", 1594 | "functional-red-black-tree": "^1.0.1", 1595 | "glob-parent": "^5.1.2", 1596 | "globals": "^13.6.0", 1597 | "ignore": "^4.0.6", 1598 | "import-fresh": "^3.0.0", 1599 | "imurmurhash": "^0.1.4", 1600 | "is-glob": "^4.0.0", 1601 | "js-yaml": "^3.13.1", 1602 | "json-stable-stringify-without-jsonify": "^1.0.1", 1603 | "levn": "^0.4.1", 1604 | "lodash.merge": "^4.6.2", 1605 | "minimatch": "^3.0.4", 1606 | "natural-compare": "^1.4.0", 1607 | "optionator": "^0.9.1", 1608 | "progress": "^2.0.0", 1609 | "regexpp": "^3.1.0", 1610 | "semver": "^7.2.1", 1611 | "strip-ansi": "^6.0.0", 1612 | "strip-json-comments": "^3.1.0", 1613 | "table": "^6.0.9", 1614 | "text-table": "^0.2.0", 1615 | "v8-compile-cache": "^2.0.3" 1616 | } 1617 | }, 1618 | "eslint-config-google": { 1619 | "version": "0.14.0", 1620 | "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", 1621 | "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", 1622 | "dev": true, 1623 | "requires": {} 1624 | }, 1625 | "eslint-scope": { 1626 | "version": "5.1.1", 1627 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 1628 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 1629 | "dev": true, 1630 | "requires": { 1631 | "esrecurse": "^4.3.0", 1632 | "estraverse": "^4.1.1" 1633 | } 1634 | }, 1635 | "eslint-utils": { 1636 | "version": "2.1.0", 1637 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 1638 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 1639 | "dev": true, 1640 | "requires": { 1641 | "eslint-visitor-keys": "^1.1.0" 1642 | }, 1643 | "dependencies": { 1644 | "eslint-visitor-keys": { 1645 | "version": "1.3.0", 1646 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 1647 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 1648 | "dev": true 1649 | } 1650 | } 1651 | }, 1652 | "eslint-visitor-keys": { 1653 | "version": "2.1.0", 1654 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 1655 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 1656 | "dev": true 1657 | }, 1658 | "espree": { 1659 | "version": "7.3.1", 1660 | "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", 1661 | "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", 1662 | "dev": true, 1663 | "requires": { 1664 | "acorn": "^7.4.0", 1665 | "acorn-jsx": "^5.3.1", 1666 | "eslint-visitor-keys": "^1.3.0" 1667 | }, 1668 | "dependencies": { 1669 | "eslint-visitor-keys": { 1670 | "version": "1.3.0", 1671 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 1672 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 1673 | "dev": true 1674 | } 1675 | } 1676 | }, 1677 | "esprima": { 1678 | "version": "4.0.1", 1679 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1680 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 1681 | "dev": true 1682 | }, 1683 | "esquery": { 1684 | "version": "1.4.0", 1685 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 1686 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 1687 | "dev": true, 1688 | "requires": { 1689 | "estraverse": "^5.1.0" 1690 | }, 1691 | "dependencies": { 1692 | "estraverse": { 1693 | "version": "5.3.0", 1694 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1695 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1696 | "dev": true 1697 | } 1698 | } 1699 | }, 1700 | "esrecurse": { 1701 | "version": "4.3.0", 1702 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1703 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1704 | "dev": true, 1705 | "requires": { 1706 | "estraverse": "^5.2.0" 1707 | }, 1708 | "dependencies": { 1709 | "estraverse": { 1710 | "version": "5.3.0", 1711 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1712 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1713 | "dev": true 1714 | } 1715 | } 1716 | }, 1717 | "estraverse": { 1718 | "version": "4.3.0", 1719 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 1720 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 1721 | "dev": true 1722 | }, 1723 | "esutils": { 1724 | "version": "2.0.3", 1725 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1726 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1727 | "dev": true 1728 | }, 1729 | "fast-deep-equal": { 1730 | "version": "3.1.3", 1731 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1732 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1733 | "dev": true 1734 | }, 1735 | "fast-json-stable-stringify": { 1736 | "version": "2.1.0", 1737 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1738 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1739 | "dev": true 1740 | }, 1741 | "fast-levenshtein": { 1742 | "version": "2.0.6", 1743 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1744 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 1745 | "dev": true 1746 | }, 1747 | "file-entry-cache": { 1748 | "version": "6.0.1", 1749 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 1750 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 1751 | "dev": true, 1752 | "requires": { 1753 | "flat-cache": "^3.0.4" 1754 | } 1755 | }, 1756 | "flat-cache": { 1757 | "version": "3.0.4", 1758 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 1759 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 1760 | "dev": true, 1761 | "requires": { 1762 | "flatted": "^3.1.0", 1763 | "rimraf": "^3.0.2" 1764 | } 1765 | }, 1766 | "flatted": { 1767 | "version": "3.2.5", 1768 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", 1769 | "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", 1770 | "dev": true 1771 | }, 1772 | "fs.realpath": { 1773 | "version": "1.0.0", 1774 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1775 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1776 | "dev": true 1777 | }, 1778 | "functional-red-black-tree": { 1779 | "version": "1.0.1", 1780 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1781 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 1782 | "dev": true 1783 | }, 1784 | "glob": { 1785 | "version": "7.2.0", 1786 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 1787 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 1788 | "dev": true, 1789 | "requires": { 1790 | "fs.realpath": "^1.0.0", 1791 | "inflight": "^1.0.4", 1792 | "inherits": "2", 1793 | "minimatch": "^3.0.4", 1794 | "once": "^1.3.0", 1795 | "path-is-absolute": "^1.0.0" 1796 | } 1797 | }, 1798 | "glob-parent": { 1799 | "version": "5.1.2", 1800 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1801 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1802 | "dev": true, 1803 | "requires": { 1804 | "is-glob": "^4.0.1" 1805 | } 1806 | }, 1807 | "globals": { 1808 | "version": "13.12.1", 1809 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", 1810 | "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", 1811 | "dev": true, 1812 | "requires": { 1813 | "type-fest": "^0.20.2" 1814 | } 1815 | }, 1816 | "has-flag": { 1817 | "version": "4.0.0", 1818 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1819 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1820 | "dev": true 1821 | }, 1822 | "ignore": { 1823 | "version": "4.0.6", 1824 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 1825 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 1826 | "dev": true 1827 | }, 1828 | "import-fresh": { 1829 | "version": "3.3.0", 1830 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1831 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1832 | "dev": true, 1833 | "requires": { 1834 | "parent-module": "^1.0.0", 1835 | "resolve-from": "^4.0.0" 1836 | } 1837 | }, 1838 | "imurmurhash": { 1839 | "version": "0.1.4", 1840 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1841 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1842 | "dev": true 1843 | }, 1844 | "inflight": { 1845 | "version": "1.0.6", 1846 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1847 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1848 | "dev": true, 1849 | "requires": { 1850 | "once": "^1.3.0", 1851 | "wrappy": "1" 1852 | } 1853 | }, 1854 | "inherits": { 1855 | "version": "2.0.4", 1856 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1857 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1858 | "dev": true 1859 | }, 1860 | "is-extglob": { 1861 | "version": "2.1.1", 1862 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1863 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1864 | "dev": true 1865 | }, 1866 | "is-fullwidth-code-point": { 1867 | "version": "3.0.0", 1868 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1869 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1870 | "dev": true 1871 | }, 1872 | "is-glob": { 1873 | "version": "4.0.3", 1874 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1875 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1876 | "dev": true, 1877 | "requires": { 1878 | "is-extglob": "^2.1.1" 1879 | } 1880 | }, 1881 | "isexe": { 1882 | "version": "2.0.0", 1883 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1884 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1885 | "dev": true 1886 | }, 1887 | "js-tokens": { 1888 | "version": "4.0.0", 1889 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1890 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1891 | "dev": true 1892 | }, 1893 | "js-yaml": { 1894 | "version": "3.14.1", 1895 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 1896 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 1897 | "dev": true, 1898 | "requires": { 1899 | "argparse": "^1.0.7", 1900 | "esprima": "^4.0.0" 1901 | } 1902 | }, 1903 | "json-schema-traverse": { 1904 | "version": "0.4.1", 1905 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1906 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1907 | "dev": true 1908 | }, 1909 | "json-stable-stringify-without-jsonify": { 1910 | "version": "1.0.1", 1911 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1912 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1913 | "dev": true 1914 | }, 1915 | "levn": { 1916 | "version": "0.4.1", 1917 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1918 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1919 | "dev": true, 1920 | "requires": { 1921 | "prelude-ls": "^1.2.1", 1922 | "type-check": "~0.4.0" 1923 | } 1924 | }, 1925 | "libcobhandemo": { 1926 | "version": "file:../libcobhandemo", 1927 | "requires": { 1928 | "cobhan": "^1.0.15", 1929 | "eslint": "^7.32.0", 1930 | "eslint-config-google": "^0.14.0" 1931 | } 1932 | }, 1933 | "lodash.merge": { 1934 | "version": "4.6.2", 1935 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1936 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1937 | "dev": true 1938 | }, 1939 | "lodash.truncate": { 1940 | "version": "4.4.2", 1941 | "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", 1942 | "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", 1943 | "dev": true 1944 | }, 1945 | "lru-cache": { 1946 | "version": "6.0.0", 1947 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1948 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1949 | "dev": true, 1950 | "requires": { 1951 | "yallist": "^4.0.0" 1952 | } 1953 | }, 1954 | "minimatch": { 1955 | "version": "3.1.2", 1956 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1957 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1958 | "dev": true, 1959 | "requires": { 1960 | "brace-expansion": "^1.1.7" 1961 | } 1962 | }, 1963 | "ms": { 1964 | "version": "2.1.2", 1965 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1966 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1967 | "dev": true 1968 | }, 1969 | "natural-compare": { 1970 | "version": "1.4.0", 1971 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1972 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1973 | "dev": true 1974 | }, 1975 | "once": { 1976 | "version": "1.4.0", 1977 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1978 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1979 | "dev": true, 1980 | "requires": { 1981 | "wrappy": "1" 1982 | } 1983 | }, 1984 | "optionator": { 1985 | "version": "0.9.1", 1986 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 1987 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 1988 | "dev": true, 1989 | "requires": { 1990 | "deep-is": "^0.1.3", 1991 | "fast-levenshtein": "^2.0.6", 1992 | "levn": "^0.4.1", 1993 | "prelude-ls": "^1.2.1", 1994 | "type-check": "^0.4.0", 1995 | "word-wrap": "^1.2.3" 1996 | } 1997 | }, 1998 | "parent-module": { 1999 | "version": "1.0.1", 2000 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 2001 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 2002 | "dev": true, 2003 | "requires": { 2004 | "callsites": "^3.0.0" 2005 | } 2006 | }, 2007 | "path-is-absolute": { 2008 | "version": "1.0.1", 2009 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2010 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 2011 | "dev": true 2012 | }, 2013 | "path-key": { 2014 | "version": "3.1.1", 2015 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2016 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2017 | "dev": true 2018 | }, 2019 | "prelude-ls": { 2020 | "version": "1.2.1", 2021 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2022 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2023 | "dev": true 2024 | }, 2025 | "process": { 2026 | "version": "0.11.10", 2027 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 2028 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" 2029 | }, 2030 | "progress": { 2031 | "version": "2.0.3", 2032 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 2033 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 2034 | "dev": true 2035 | }, 2036 | "punycode": { 2037 | "version": "2.1.1", 2038 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 2039 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 2040 | "dev": true 2041 | }, 2042 | "regexpp": { 2043 | "version": "3.2.0", 2044 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 2045 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 2046 | "dev": true 2047 | }, 2048 | "require-from-string": { 2049 | "version": "2.0.2", 2050 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 2051 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 2052 | "dev": true 2053 | }, 2054 | "resolve-from": { 2055 | "version": "4.0.0", 2056 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2057 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2058 | "dev": true 2059 | }, 2060 | "rimraf": { 2061 | "version": "3.0.2", 2062 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2063 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2064 | "dev": true, 2065 | "requires": { 2066 | "glob": "^7.1.3" 2067 | } 2068 | }, 2069 | "semver": { 2070 | "version": "7.3.5", 2071 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 2072 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 2073 | "dev": true, 2074 | "requires": { 2075 | "lru-cache": "^6.0.0" 2076 | } 2077 | }, 2078 | "shebang-command": { 2079 | "version": "2.0.0", 2080 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2081 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2082 | "dev": true, 2083 | "requires": { 2084 | "shebang-regex": "^3.0.0" 2085 | } 2086 | }, 2087 | "shebang-regex": { 2088 | "version": "3.0.0", 2089 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2090 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2091 | "dev": true 2092 | }, 2093 | "slice-ansi": { 2094 | "version": "4.0.0", 2095 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", 2096 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", 2097 | "dev": true, 2098 | "requires": { 2099 | "ansi-styles": "^4.0.0", 2100 | "astral-regex": "^2.0.0", 2101 | "is-fullwidth-code-point": "^3.0.0" 2102 | } 2103 | }, 2104 | "sprintf-js": { 2105 | "version": "1.0.3", 2106 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2107 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2108 | "dev": true 2109 | }, 2110 | "string-width": { 2111 | "version": "4.2.3", 2112 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2113 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2114 | "dev": true, 2115 | "requires": { 2116 | "emoji-regex": "^8.0.0", 2117 | "is-fullwidth-code-point": "^3.0.0", 2118 | "strip-ansi": "^6.0.1" 2119 | } 2120 | }, 2121 | "strip-ansi": { 2122 | "version": "6.0.1", 2123 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2124 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2125 | "dev": true, 2126 | "requires": { 2127 | "ansi-regex": "^5.0.1" 2128 | } 2129 | }, 2130 | "strip-json-comments": { 2131 | "version": "3.1.1", 2132 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2133 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2134 | "dev": true 2135 | }, 2136 | "supports-color": { 2137 | "version": "7.2.0", 2138 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2139 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2140 | "dev": true, 2141 | "requires": { 2142 | "has-flag": "^4.0.0" 2143 | } 2144 | }, 2145 | "table": { 2146 | "version": "6.8.0", 2147 | "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", 2148 | "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", 2149 | "dev": true, 2150 | "requires": { 2151 | "ajv": "^8.0.1", 2152 | "lodash.truncate": "^4.4.2", 2153 | "slice-ansi": "^4.0.0", 2154 | "string-width": "^4.2.3", 2155 | "strip-ansi": "^6.0.1" 2156 | }, 2157 | "dependencies": { 2158 | "ajv": { 2159 | "version": "8.10.0", 2160 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", 2161 | "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", 2162 | "dev": true, 2163 | "requires": { 2164 | "fast-deep-equal": "^3.1.1", 2165 | "json-schema-traverse": "^1.0.0", 2166 | "require-from-string": "^2.0.2", 2167 | "uri-js": "^4.2.2" 2168 | } 2169 | }, 2170 | "json-schema-traverse": { 2171 | "version": "1.0.0", 2172 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", 2173 | "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", 2174 | "dev": true 2175 | } 2176 | } 2177 | }, 2178 | "text-table": { 2179 | "version": "0.2.0", 2180 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2181 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2182 | "dev": true 2183 | }, 2184 | "type-check": { 2185 | "version": "0.4.0", 2186 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2187 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2188 | "dev": true, 2189 | "requires": { 2190 | "prelude-ls": "^1.2.1" 2191 | } 2192 | }, 2193 | "type-fest": { 2194 | "version": "0.20.2", 2195 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2196 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2197 | "dev": true 2198 | }, 2199 | "uri-js": { 2200 | "version": "4.4.1", 2201 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2202 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2203 | "dev": true, 2204 | "requires": { 2205 | "punycode": "^2.1.0" 2206 | } 2207 | }, 2208 | "v8-compile-cache": { 2209 | "version": "2.3.0", 2210 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 2211 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 2212 | "dev": true 2213 | }, 2214 | "which": { 2215 | "version": "2.0.2", 2216 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2217 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2218 | "dev": true, 2219 | "requires": { 2220 | "isexe": "^2.0.0" 2221 | } 2222 | }, 2223 | "word-wrap": { 2224 | "version": "1.2.3", 2225 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2226 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2227 | "dev": true 2228 | }, 2229 | "wrappy": { 2230 | "version": "1.0.2", 2231 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2232 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2233 | "dev": true 2234 | }, 2235 | "yallist": { 2236 | "version": "4.0.0", 2237 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2238 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2239 | "dev": true 2240 | } 2241 | } 2242 | } 2243 | --------------------------------------------------------------------------------