├── rustfmt.toml ├── .prettierignore ├── .github ├── FUNDING.yml └── workflows │ ├── docker.yaml │ ├── linux-musl.yaml │ ├── macos.yaml │ ├── linux.yaml │ └── windows.yaml ├── .yarnrc ├── .dockerignore ├── napi ├── src │ ├── sys │ │ ├── bindings.h │ │ ├── mod.rs │ │ └── stable.rs │ ├── task.rs │ ├── version.rs │ ├── call_context.rs │ ├── async_work.rs │ └── lib.rs ├── Cargo.toml └── build.rs ├── test_module ├── yarn.lock ├── build.rs ├── package.json ├── Cargo.toml ├── spawn.js ├── fuzzy.js └── src │ └── lib.rs ├── napi-derive-example ├── build.rs ├── Cargo.toml └── src │ └── lib.rs ├── .npmignore ├── Cargo.toml ├── .editorconfig ├── napi-derive ├── Cargo.toml ├── README.md └── src │ └── lib.rs ├── Dockerfile.alpine ├── package.json ├── LICENSE ├── scripts └── napi.js ├── .gitignore ├── CODE_OF_CONDUCT.md ├── README.md └── yarn.lock /rustfmt.toml: -------------------------------------------------------------------------------- 1 | tab_spaces = 2 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | target 2 | node_modules -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [Brooooooklyn] 2 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.npmjs.org" -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | target 2 | test_module/target 3 | node_modules 4 | -------------------------------------------------------------------------------- /napi/src/sys/bindings.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include -------------------------------------------------------------------------------- /test_module/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | -------------------------------------------------------------------------------- /test_module/build.rs: -------------------------------------------------------------------------------- 1 | extern crate napi_build; 2 | 3 | fn main() { 4 | use napi_build::setup; 5 | 6 | setup(); 7 | } 8 | -------------------------------------------------------------------------------- /napi-derive-example/build.rs: -------------------------------------------------------------------------------- 1 | extern crate napi_build; 2 | 3 | fn main() { 4 | use napi_build::setup; 5 | 6 | setup(); 7 | } 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | target 2 | build 3 | napi 4 | napi-derive 5 | napi-derive-example 6 | test_module 7 | .yarnrc 8 | Cargo.lock 9 | rustfmt.toml 10 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "./build", 4 | "./napi", 5 | "./napi-derive", 6 | "./napi-derive-example" 7 | ] 8 | exclude = ["./test_module"] 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | indent_size = 2 9 | indent_style = space 10 | -------------------------------------------------------------------------------- /napi/src/sys/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | #![allow(non_camel_case_types)] 3 | #![allow(non_snake_case)] 4 | #![allow(dead_code)] 5 | 6 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 7 | 8 | mod stable; 9 | pub use self::stable::Status; 10 | -------------------------------------------------------------------------------- /test_module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-module", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "build": "cargo build && node ../scripts/napi.js ./index", 6 | "build-release": "cargo build --release && node ../scripts/napi.js --release ./index", 7 | "test": "node ./index.js" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /napi/src/task.rs: -------------------------------------------------------------------------------- 1 | use crate::{Env, Result, Value, ValueType}; 2 | 3 | pub trait Task { 4 | type Output: Send + Sized + 'static; 5 | type JsValue: ValueType; 6 | 7 | fn compute(&self) -> Result; 8 | 9 | fn resolve(&self, env: &mut Env, output: Self::Output) -> Result>; 10 | } 11 | -------------------------------------------------------------------------------- /test_module/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-module" 3 | version = "0.1.0" 4 | authors = ["LongYinan "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | napi-rs = { path = "../napi" } 12 | napi-rs-derive = { path = "../napi-derive" } 13 | 14 | [build-dependencies] 15 | napi-build = { path = "../build" } 16 | -------------------------------------------------------------------------------- /napi-derive-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "napi-derive-example" 3 | version = "0.1.0" 4 | authors = ["LongYinan "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | napi-rs = { path = "../napi" } 12 | napi-rs-derive = { path = "../napi-derive" } 13 | 14 | [build-dependencies] 15 | napi-build = { path = "../build" } 16 | -------------------------------------------------------------------------------- /test_module/spawn.js: -------------------------------------------------------------------------------- 1 | const testModule = require('./index.node') 2 | 3 | function testSpawnThread(n) { 4 | console.info('=== Test spawn task to threadpool') 5 | return testModule.testSpawnThread(n) 6 | } 7 | 8 | testSpawnThread(20) 9 | .then((value) => { 10 | console.assert(value === 6765) 11 | console.info('=== fibonacci result', value) 12 | }) 13 | .catch((e) => { 14 | console.error(e) 15 | process.exit(1) 16 | }) 17 | -------------------------------------------------------------------------------- /napi-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "napi-rs-derive" 3 | version = "0.2.0" 4 | authors = ["LongYinan "] 5 | edition = "2018" 6 | description = "N-API procedural macros" 7 | readme = "README.md" 8 | repository = "https://github.com/Brooooooklyn/napi-rs" 9 | license = "MIT" 10 | keywords = ["NodeJS", "FFI", "NAPI", "n-api"] 11 | 12 | [dependencies] 13 | syn = { version = "1.0", features = ["fold", "full"] } 14 | quote = "1.0" 15 | proc-macro2 = "1.0" 16 | 17 | [lib] 18 | proc-macro = true 19 | -------------------------------------------------------------------------------- /Dockerfile.alpine: -------------------------------------------------------------------------------- 1 | FROM rust:alpine 2 | 3 | ENV RUSTFLAGS="-C target-feature=-crt-static" 4 | 5 | RUN sed -i -e 's/v[[:digit:]]\..*\//edge\//g' /etc/apk/repositories && \ 6 | apk update && \ 7 | apk add nodejs yarn clang musl-dev llvm-dev curl && \ 8 | export NODE_VERSION=$(node -e "console.log(process.version)") && \ 9 | curl -fsSLO $(node -e "console.log(process.release.headersUrl)") && \ 10 | tar -xf "node-$NODE_VERSION-headers.tar.gz" && \ 11 | mv "node-$NODE_VERSION/include/node" include && \ 12 | rm -rf "node-$NODE_VERSION" && \ 13 | rm "node-$NODE_VERSION-headers.tar.gz" -------------------------------------------------------------------------------- /napi-derive/README.md: -------------------------------------------------------------------------------- 1 | # napi-derive 2 | 3 | ## js_function 4 | 5 | ```rust 6 | #[macro_use] 7 | extern crate napi_rs_derive; 8 | 9 | use napi_rs::{Result, Value, CallContext, Number}; 10 | use std::convert::TryInto; 11 | 12 | #[js_function(1)] 13 | fn fibonacci(ctx: CallContext) -> Result> { 14 | let n = ctx.get::(0)?.try_into()?; 15 | ctx.env.create_int64(fibonacci_native(n)) 16 | } 17 | 18 | #[inline] 19 | fn fibonacci_native(n: i64) -> i64 { 20 | match n { 21 | 1 | 2 => 1, 22 | _ => fibonacci_native(n - 1) + fibonacci_native(n - 2) 23 | } 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /napi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "napi-rs" 3 | version = "0.3.1" 4 | authors = ["Nathan Sobo ", "Yinan Long "] 5 | license = "MIT" 6 | description = "N-API bindings" 7 | readme = "README.md" 8 | repository = "https://github.com/Brooooooklyn/napi-rs" 9 | keywords = ["NodeJS", "FFI", "NAPI", "n-api"] 10 | edition = "2018" 11 | 12 | [target.'cfg(windows)'.build-dependencies] 13 | flate2 = "1.0" 14 | reqwest = { version = "0.10", features = ["native-tls", "blocking"] } 15 | tar = "0.4" 16 | 17 | [build-dependencies] 18 | bindgen = "0.54" 19 | glob = "0.3" 20 | napi-build = { version = "0.1", path = "../build" } 21 | regex = "1.3" 22 | semver = "0.10" -------------------------------------------------------------------------------- /napi/src/version.rs: -------------------------------------------------------------------------------- 1 | use crate::{sys, Error, Status}; 2 | use std::convert::TryFrom; 3 | use std::ffi::CStr; 4 | 5 | #[derive(Debug, Clone, Copy)] 6 | pub struct NodeVersion { 7 | pub major: u32, 8 | pub minor: u32, 9 | pub patch: u32, 10 | pub release: &'static str, 11 | } 12 | 13 | impl TryFrom for NodeVersion { 14 | type Error = Error; 15 | 16 | fn try_from(value: sys::napi_node_version) -> Result { 17 | Ok(NodeVersion { 18 | major: value.major, 19 | minor: value.minor, 20 | patch: value.patch, 21 | release: unsafe { 22 | CStr::from_ptr(value.release).to_str().map_err(|_| Error { 23 | status: Status::StringExpected, 24 | reason: Some("Invalid release name".to_owned()), 25 | })? 26 | }, 27 | }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test_module/fuzzy.js: -------------------------------------------------------------------------------- 1 | const { exec } = require('child_process') 2 | 3 | Array.from({ length: 500 }) 4 | .reduce(async (acc) => { 5 | await acc 6 | await run() 7 | }, null) 8 | .then(() => { 9 | console.info(`Fuzzy test success, passed ${500} tests.`) 10 | }) 11 | .catch((e) => { 12 | console.error(e) 13 | process.exit(1) 14 | }) 15 | 16 | const run = () => { 17 | return new Promise((resolve, reject) => { 18 | const testProcess = exec('node ./spawn.js', { 19 | env: process.env, 20 | }) 21 | testProcess.stdout.pipe(process.stdout) 22 | testProcess.stderr.pipe(process.stderr) 23 | testProcess.on('error', (err) => { 24 | reject(err) 25 | }) 26 | testProcess.on('exit', (code) => { 27 | if (code) { 28 | reject(new TypeError(`Child process exit code ${code}`)) 29 | } else { 30 | resolve() 31 | } 32 | }) 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/docker.yaml: -------------------------------------------------------------------------------- 1 | name: Docker nightly build 2 | 3 | on: 4 | schedule: 5 | - cron: '0 1 * * *' 6 | 7 | jobs: 8 | build_image: 9 | name: Build rust-nodejs-alpine:lts 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Login to registry 16 | run: | 17 | docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD $DOCKER_REGISTRY_URL 18 | env: 19 | DOCKER_REGISTRY_URL: docker.pkg.github.com 20 | DOCKER_USERNAME: ${{ github.actor }} 21 | DOCKER_PASSWORD: ${{ secrets.GITHUB_TOKEN }} 22 | 23 | - name: Build docker image 24 | run: | 25 | docker build . -f Dockerfile.alpine --pull --no-cache -t docker.pkg.github.com/napi-rs/napi-rs/rust-nodejs-alpine:lts 26 | 27 | - name: Push docker image 28 | run: docker push docker.pkg.github.com/napi-rs/napi-rs/rust-nodejs-alpine:lts 29 | -------------------------------------------------------------------------------- /napi/src/call_context.rs: -------------------------------------------------------------------------------- 1 | use crate::{sys, Any, Env, Error, Result, Status, Value, ValueType}; 2 | 3 | pub struct CallContext<'env, T: ValueType = Any> { 4 | pub env: &'env Env, 5 | pub this: Value, 6 | args: [sys::napi_value; 8], 7 | arg_len: usize, 8 | } 9 | 10 | impl<'env, T: ValueType> CallContext<'env, T> { 11 | #[inline] 12 | pub fn new( 13 | env: &'env Env, 14 | this: sys::napi_value, 15 | args: [sys::napi_value; 8], 16 | arg_len: usize, 17 | ) -> Result { 18 | Ok(Self { 19 | env, 20 | this: Value::::from_raw(env.0, this)?, 21 | args, 22 | arg_len, 23 | }) 24 | } 25 | 26 | #[inline] 27 | pub fn get(&self, index: usize) -> Result> { 28 | if index + 1 > self.arg_len { 29 | Err(Error { 30 | status: Status::GenericFailure, 31 | reason: Some("Arguments index out of range".to_owned()), 32 | }) 33 | } else { 34 | Value::::from_raw(self.env.0, self.args[index]) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /napi-derive-example/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate napi_rs as napi; 3 | #[macro_use] 4 | extern crate napi_rs_derive; 5 | 6 | use napi::{Any, CallContext, Env, Error, Number, Object, Result, Status, Value}; 7 | use std::convert::TryInto; 8 | 9 | register_module!(test_module, init); 10 | 11 | fn init(env: &Env, exports: &mut Value) -> Result<()> { 12 | exports.set_named_property("testThrow", env.create_function("testThrow", test_throw)?)?; 13 | 14 | exports.set_named_property("fibonacci", env.create_function("fibonacci", fibonacci)?)?; 15 | Ok(()) 16 | } 17 | 18 | #[js_function] 19 | fn test_throw(_ctx: CallContext) -> Result> { 20 | Err(Error::from_status(Status::GenericFailure)) 21 | } 22 | 23 | #[js_function(1)] 24 | fn fibonacci(ctx: CallContext) -> Result> { 25 | let n = ctx.get::(0)?.try_into()?; 26 | ctx.env.create_int64(fibonacci_native(n)) 27 | } 28 | 29 | #[inline] 30 | fn fibonacci_native(n: i64) -> i64 { 31 | match n { 32 | 1 | 2 => 1, 33 | _ => fibonacci_native(n - 1) + fibonacci_native(n - 2), 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test_module/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate napi_rs as napi; 3 | #[macro_use] 4 | extern crate napi_rs_derive; 5 | 6 | use napi::{Any, CallContext, Env, Error, Number, Object, Result, Status, Task, Value}; 7 | use std::convert::TryInto; 8 | 9 | register_module!(test_module, init); 10 | 11 | fn init(env: &Env, exports: &mut Value) -> Result<()> { 12 | exports.set_named_property("testThrow", env.create_function("testThrow", test_throw)?)?; 13 | exports.set_named_property( 14 | "testSpawnThread", 15 | env.create_function("testSpawnThread", test_spawn_thread)?, 16 | )?; 17 | Ok(()) 18 | } 19 | 20 | struct ComputeFib { 21 | n: u32, 22 | } 23 | 24 | impl ComputeFib { 25 | pub fn new(n: u32) -> ComputeFib { 26 | ComputeFib { n } 27 | } 28 | } 29 | 30 | impl Task for ComputeFib { 31 | type Output = u32; 32 | type JsValue = Number; 33 | 34 | fn compute(&self) -> Result { 35 | Ok(fibonacci_native(self.n)) 36 | } 37 | 38 | fn resolve(&self, env: &mut Env, output: Self::Output) -> Result> { 39 | env.create_uint32(output) 40 | } 41 | } 42 | 43 | #[inline] 44 | fn fibonacci_native(n: u32) -> u32 { 45 | match n { 46 | 1 | 2 => 1, 47 | _ => fibonacci_native(n - 1) + fibonacci_native(n - 2), 48 | } 49 | } 50 | 51 | #[js_function(1)] 52 | fn test_spawn_thread(ctx: CallContext) -> Result> { 53 | let n = ctx.get::(0)?; 54 | let task = ComputeFib::new(n.try_into()?); 55 | ctx.env.spawn(task) 56 | } 57 | 58 | #[js_function] 59 | fn test_throw(_ctx: CallContext) -> Result> { 60 | Err(Error::from_status(Status::GenericFailure)) 61 | } 62 | -------------------------------------------------------------------------------- /.github/workflows/linux-musl.yaml: -------------------------------------------------------------------------------- 1 | name: Musl 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | name: stable - x86_64-unknown-linux-musl - node@${{ matrix.node }} 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | node: ['10', '12', '13', '14'] 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Log in to registry 18 | run: | 19 | docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD $DOCKER_REGISTRY_URL 20 | env: 21 | DOCKER_REGISTRY_URL: docker.pkg.github.com 22 | DOCKER_USERNAME: ${{ github.actor }} 23 | DOCKER_PASSWORD: ${{ secrets.GITHUB_TOKEN }} 24 | 25 | - name: Pull docker image 26 | run: | 27 | docker pull docker.pkg.github.com/napi-rs/napi-rs/rust-nodejs-alpine:lts 28 | docker tag docker.pkg.github.com/napi-rs/napi-rs/rust-nodejs-alpine:lts builder 29 | 30 | - name: Run check 31 | run: | 32 | docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder cargo check --all --bins --examples --tests -vvv 33 | 34 | - name: Run tests 35 | run: | 36 | docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder cargo test -p napi-rs --lib -- --nocapture 37 | 38 | - name: Build native module 39 | run: | 40 | docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder sh -c "yarn && cd test_module && yarn build" 41 | env: 42 | RUST_BACKTRACE: 1 43 | 44 | - name: Fuzzy 45 | run: docker run --rm -v $(pwd):/napi-rs -w /napi-rs/test_module node:${{ matrix.node }}-alpine node fuzzy.js 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "napi-rs", 3 | "version": "0.2.4", 4 | "description": "A minimal library for building compiled Node add-ons in Rust.", 5 | "bin": { 6 | "napi": "scripts/napi.js" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git@github.com:Brooooooklyn/napi-rs.git" 11 | }, 12 | "maintainers": [ 13 | { 14 | "name": "LongYinan", 15 | "email": "lynweklm@gmail.com", 16 | "homepage": "https://github.com/Brooooooklyn" 17 | } 18 | ], 19 | "license": "MIT", 20 | "scripts": { 21 | "format": "run-p format:md format:json format:yaml format:source format:rs", 22 | "format:md": "prettier --parser markdown --write './**/*.md'", 23 | "format:json": "prettier --parser json --write './**/*.json'", 24 | "format:rs": "cargo fmt", 25 | "format:source": "prettier --config ./package.json --write './**/*.js'", 26 | "format:yaml": "prettier --parser yaml --write './**/*.{yml,yaml}'" 27 | }, 28 | "bugs": { 29 | "url": "https://github.com/Brooooooklyn/napi-rs/issues" 30 | }, 31 | "homepage": "https://github.com/Brooooooklyn/napi-rs#readme", 32 | "dependencies": { 33 | "minimist": "^1.2.5", 34 | "toml": "^3.0.0" 35 | }, 36 | "prettier": { 37 | "printWidth": 80, 38 | "semi": false, 39 | "singleQuote": true, 40 | "trailingComma": "all", 41 | "arrowParens": "always" 42 | }, 43 | "files": ["scripts/napi.js", "LICENSE"], 44 | "lint-staged": { 45 | "*.js": ["prettier --write"], 46 | "*.@(yml|yaml)": ["prettier --parser yaml --write"], 47 | "*.json": ["prettier --parser json --write"], 48 | "*.md": ["prettier --parser markdown --write"] 49 | }, 50 | "husky": { 51 | "hooks": { 52 | "pre-commit": "lint-staged && cargo fmt --all" 53 | } 54 | }, 55 | "devDependencies": { 56 | "@types/node": "^14.0.13", 57 | "husky": "^4.2.5", 58 | "lint-staged": "^10.2.10", 59 | "npm-run-all": "^4.1.5", 60 | "prettier": "^2.0.5" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 LongYinan 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 | 23 | MIT License 24 | 25 | Copyright (c) 2018 GitHub 26 | 27 | Permission is hereby granted, free of charge, to any person obtaining a copy 28 | of this software and associated documentation files (the "Software"), to deal 29 | in the Software without restriction, including without limitation the rights 30 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31 | copies of the Software, and to permit persons to whom the Software is 32 | furnished to do so, subject to the following conditions: 33 | 34 | The above copyright notice and this permission notice shall be included in all 35 | copies or substantial portions of the Software. 36 | 37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 43 | SOFTWARE. 44 | -------------------------------------------------------------------------------- /.github/workflows/macos.yaml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build_and_test: 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | node: ['10', '12', '13', '14'] 11 | 12 | name: stable - x86_64-apple-darwin - node@${{ matrix.node }} 13 | runs-on: macos-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | 18 | - name: Setup node 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: ${{ matrix.node }} 22 | 23 | - name: Install stable 24 | uses: actions-rs/toolchain@v1 25 | with: 26 | toolchain: stable-x86_64-apple-darwin 27 | profile: minimal 28 | override: true 29 | 30 | - name: Generate Cargo.lock 31 | uses: actions-rs/cargo@v1 32 | with: 33 | command: generate-lockfile 34 | - name: Cache cargo registry 35 | uses: actions/cache@v1 36 | with: 37 | path: ~/.cargo/registry 38 | key: stable-x86_64-apple-darwin-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }} 39 | - name: Cache cargo index 40 | uses: actions/cache@v1 41 | with: 42 | path: ~/.cargo/git 43 | key: stable-x86_64-apple-darwin-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }} 44 | - name: Cache cargo build 45 | uses: actions/cache@v1 46 | with: 47 | path: target 48 | key: stable-x86_64-apple-darwin-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }} 49 | 50 | - name: Check build 51 | uses: actions-rs/cargo@v1 52 | with: 53 | command: check 54 | args: --all --bins --examples --tests -vvv 55 | 56 | - name: Tests 57 | uses: actions-rs/cargo@v1 58 | timeout-minutes: 5 59 | with: 60 | command: test 61 | args: -p napi-rs --lib -- --nocapture 62 | 63 | - name: Fuzzy tests 64 | run: | 65 | yarn 66 | cd test_module 67 | yarn build 68 | node fuzzy.js 69 | env: 70 | RUST_BACKTRACE: 1 71 | 72 | - name: Clear the cargo caches 73 | run: | 74 | cargo install cargo-cache --no-default-features --features ci-autoclean 75 | cargo-cache 76 | -------------------------------------------------------------------------------- /.github/workflows/linux.yaml: -------------------------------------------------------------------------------- 1 | name: Linux 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build_and_test: 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | node: ['10', '12', '13', '14'] 11 | 12 | name: stable - x86_64-unknown-linux-gnu - node@${{ matrix.node }} 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | 18 | - name: Setup node 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: ${{ matrix.node }} 22 | 23 | - name: Install stable 24 | uses: actions-rs/toolchain@v1 25 | with: 26 | toolchain: stable-x86_64-unknown-linux-gnu 27 | profile: minimal 28 | override: true 29 | 30 | - name: Generate Cargo.lock 31 | uses: actions-rs/cargo@v1 32 | with: 33 | command: generate-lockfile 34 | - name: Cache cargo registry 35 | uses: actions/cache@v1 36 | with: 37 | path: ~/.cargo/registry 38 | key: stable-x86_64-unknown-linux-gnu-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }} 39 | - name: Cache cargo index 40 | uses: actions/cache@v1 41 | with: 42 | path: ~/.cargo/git 43 | key: stable-x86_64-unknown-linux-gnu-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }} 44 | - name: Cache cargo build 45 | uses: actions/cache@v1 46 | with: 47 | path: target 48 | key: stable-x86_64-unknown-linux-gnu-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }} 49 | 50 | - name: Check build 51 | uses: actions-rs/cargo@v1 52 | with: 53 | command: check 54 | args: --all --bins --examples --tests -vvv 55 | 56 | - name: Tests 57 | uses: actions-rs/cargo@v1 58 | timeout-minutes: 5 59 | with: 60 | command: test 61 | args: -p napi-rs --lib -- --nocapture 62 | 63 | - name: Fuzzy tests 64 | run: | 65 | yarn 66 | cd test_module 67 | yarn build 68 | node fuzzy.js 69 | env: 70 | RUST_BACKTRACE: 1 71 | 72 | - name: Clear the cargo caches 73 | run: | 74 | cargo install cargo-cache --no-default-features --features ci-autoclean 75 | cargo-cache 76 | -------------------------------------------------------------------------------- /scripts/napi.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const parseArgs = require('minimist') 4 | const path = require('path') 5 | const os = require('os') 6 | const toml = require('toml') 7 | const fs = require('fs') 8 | 9 | let tomlContentString 10 | let tomlContent 11 | let moduleName 12 | 13 | try { 14 | tomlContentString = fs.readFileSync( 15 | path.join(process.cwd(), 'Cargo.toml'), 16 | 'utf-8', 17 | ) 18 | } catch { 19 | throw new TypeError('Can not find Cargo.toml in process.cwd') 20 | } 21 | 22 | try { 23 | tomlContent = toml.parse(tomlContentString) 24 | } catch { 25 | throw new TypeError('Can not parse the Cargo.toml') 26 | } 27 | 28 | if (tomlContent.package && tomlContent.package.name) { 29 | moduleName = tomlContent.package.name.replace(/-/g, '_') 30 | } else { 31 | throw new TypeError('No package.name field in Cargo.toml') 32 | } 33 | 34 | const argv = parseArgs(process.argv.slice(2), { 35 | boolean: ['release', 'platform', 'musl'], 36 | }) 37 | 38 | const platform = os.platform() 39 | let libExt 40 | let dylibName = moduleName 41 | 42 | // Platform based massaging for build commands 43 | switch (platform) { 44 | case 'darwin': 45 | libExt = '.dylib' 46 | dylibName = `lib${moduleName}` 47 | break 48 | case 'win32': 49 | libExt = '.dll' 50 | break 51 | case 'linux': 52 | dylibName = `lib${moduleName}` 53 | libExt = '.so' 54 | break 55 | default: 56 | console.error( 57 | 'Operating system not currently supported or recognized by the build script', 58 | ) 59 | process.exit(1) 60 | } 61 | 62 | const targetDir = argv.release ? 'release' : 'debug' 63 | 64 | const platformName = argv.musl ? '.musl' : argv.platform ? `.${platform}` : '' 65 | 66 | let subcommand = 67 | argv._[0] || 68 | path.join('target', targetDir, `${moduleName}${platformName}.node`) 69 | const parsedDist = path.parse(subcommand) 70 | 71 | if (!parsedDist.name || parsedDist.name === '.') { 72 | subcommand = moduleName 73 | } 74 | 75 | if (!parsedDist.ext) { 76 | subcommand = `${subcommand}${platformName}.node` 77 | } 78 | 79 | const pos = __dirname.indexOf('node_modules') 80 | 81 | const dylibContent = fs.readFileSync( 82 | path.join( 83 | __dirname.substring(0, pos), 84 | 'target', 85 | targetDir, 86 | `${dylibName}${libExt}`, 87 | ), 88 | ) 89 | 90 | fs.writeFileSync(subcommand, dylibContent) 91 | -------------------------------------------------------------------------------- /.github/workflows/windows.yaml: -------------------------------------------------------------------------------- 1 | name: Windows 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build_and_test: 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | node: ['10', '12', '13', '14'] 11 | target: 12 | - x86_64-pc-windows-msvc 13 | 14 | name: stable - ${{ matrix.target }} - node@${{ matrix.node }} 15 | runs-on: windows-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Setup node 21 | uses: actions/setup-node@v1 22 | with: 23 | node-version: ${{ matrix.node }} 24 | - name: Install stable 25 | uses: actions-rs/toolchain@v1 26 | with: 27 | toolchain: stable-${{ matrix.target }} 28 | profile: minimal 29 | override: true 30 | - name: Install llvm 31 | run: choco install -y llvm 32 | - name: set environment variables 33 | uses: allenevans/set-env@v1.0.0 34 | with: 35 | LIBCLANG_PATH: 'C:\Program Files\LLVM\bin' 36 | - name: Generate Cargo.lock 37 | uses: actions-rs/cargo@v1 38 | with: 39 | command: generate-lockfile 40 | - name: Cache cargo registry 41 | uses: actions/cache@v1 42 | with: 43 | path: ~/.cargo/registry 44 | key: stable-${{ matrix.target }}-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }} 45 | - name: Cache cargo index 46 | uses: actions/cache@v1 47 | with: 48 | path: ~/.cargo/git 49 | key: stable-${{ matrix.target }}-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }} 50 | - name: Cache cargo build 51 | uses: actions/cache@v1 52 | with: 53 | path: target 54 | key: stable-${{ matrix.target }}-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }} 55 | 56 | - name: Check build 57 | uses: actions-rs/cargo@v1 58 | with: 59 | command: check 60 | args: -p napi-rs -vvv 61 | 62 | - name: Tests 63 | uses: actions-rs/cargo@v1 64 | timeout-minutes: 5 65 | with: 66 | command: test 67 | args: -p napi-rs --lib -- --nocapture 68 | 69 | - name: Fuzzy tests 70 | run: | 71 | yarn 72 | cd test_module 73 | yarn build 74 | node fuzzy.js 75 | env: 76 | RUST_BACKTRACE: 1 77 | 78 | - name: Clear the cargo caches 79 | run: | 80 | cargo install cargo-cache --no-default-features --features ci-autoclean 81 | cargo-cache 82 | -------------------------------------------------------------------------------- /napi/src/sys/stable.rs: -------------------------------------------------------------------------------- 1 | use super::napi_status; 2 | 3 | #[derive(Eq, PartialEq, Debug, Clone, Copy)] 4 | pub enum Status { 5 | Ok, 6 | InvalidArg, 7 | ObjectExpected, 8 | StringExpected, 9 | NameExpected, 10 | FunctionExpected, 11 | NumberExpected, 12 | BooleanExpected, 13 | ArrayExpected, 14 | GenericFailure, 15 | PendingException, 16 | Cancelled, 17 | EscapeCalledTwice, 18 | HandleScopeMismatch, 19 | CallbackScopeMismatch, 20 | QueueFull, 21 | Closing, 22 | BigintExpected, 23 | Unknown, 24 | } 25 | 26 | impl From for Status { 27 | fn from(code: napi_status) -> Self { 28 | use self::napi_status::*; 29 | use Status::*; 30 | 31 | match code { 32 | napi_ok => Ok, 33 | napi_invalid_arg => InvalidArg, 34 | napi_object_expected => ObjectExpected, 35 | napi_string_expected => StringExpected, 36 | napi_name_expected => NameExpected, 37 | napi_function_expected => FunctionExpected, 38 | napi_number_expected => NumberExpected, 39 | napi_boolean_expected => BooleanExpected, 40 | napi_array_expected => ArrayExpected, 41 | napi_generic_failure => GenericFailure, 42 | napi_pending_exception => PendingException, 43 | napi_cancelled => Cancelled, 44 | napi_escape_called_twice => EscapeCalledTwice, 45 | napi_handle_scope_mismatch => HandleScopeMismatch, 46 | napi_callback_scope_mismatch => CallbackScopeMismatch, 47 | napi_queue_full => QueueFull, 48 | napi_closing => Closing, 49 | napi_bigint_expected => BigintExpected, 50 | _ => Unknown, 51 | } 52 | } 53 | } 54 | 55 | impl Into for Status { 56 | fn into(self) -> napi_status { 57 | match self { 58 | Self::Ok => napi_status::napi_ok, 59 | Self::InvalidArg => napi_status::napi_invalid_arg, 60 | Self::ObjectExpected => napi_status::napi_object_expected, 61 | Self::StringExpected => napi_status::napi_string_expected, 62 | Self::NameExpected => napi_status::napi_name_expected, 63 | Self::FunctionExpected => napi_status::napi_function_expected, 64 | Self::NumberExpected => napi_status::napi_number_expected, 65 | Self::BooleanExpected => napi_status::napi_boolean_expected, 66 | Self::ArrayExpected => napi_status::napi_array_expected, 67 | Self::GenericFailure => napi_status::napi_generic_failure, 68 | Self::PendingException => napi_status::napi_pending_exception, 69 | Self::Cancelled => napi_status::napi_cancelled, 70 | Self::EscapeCalledTwice => napi_status::napi_escape_called_twice, 71 | Self::HandleScopeMismatch => napi_status::napi_handle_scope_mismatch, 72 | Self::CallbackScopeMismatch => napi_status::napi_callback_scope_mismatch, 73 | Self::QueueFull => napi_status::napi_queue_full, 74 | Self::Closing => napi_status::napi_closing, 75 | Self::BigintExpected => napi_status::napi_bigint_expected, 76 | Self::Unknown => napi_status::napi_generic_failure, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | *.log 3 | .DS_Store 4 | Cargo.lock 5 | node_modules 6 | napi/src/sys/bindings.rs 7 | *.node 8 | build/LICENSE 9 | napi/LICENSE 10 | napi/README.md 11 | napi-derive/LICENSE 12 | 13 | # Created by https://www.gitignore.io/api/node 14 | # Edit at https://www.gitignore.io/?templates=node 15 | 16 | ### Node ### 17 | # Logs 18 | logs 19 | *.log 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | lerna-debug.log* 24 | 25 | # Diagnostic reports (https://nodejs.org/api/report.html) 26 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 27 | 28 | # Runtime data 29 | pids 30 | *.pid 31 | *.seed 32 | *.pid.lock 33 | 34 | # Directory for instrumented libs generated by jscoverage/JSCover 35 | lib-cov 36 | 37 | # Coverage directory used by tools like istanbul 38 | coverage 39 | *.lcov 40 | 41 | # nyc test coverage 42 | .nyc_output 43 | 44 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 45 | .grunt 46 | 47 | # Bower dependency directory (https://bower.io/) 48 | bower_components 49 | 50 | # node-waf configuration 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | build/Release 55 | 56 | # Dependency directories 57 | node_modules/ 58 | jspm_packages/ 59 | 60 | # TypeScript v1 declaration files 61 | typings/ 62 | 63 | # TypeScript cache 64 | *.tsbuildinfo 65 | 66 | # Optional npm cache directory 67 | .npm 68 | 69 | # Optional eslint cache 70 | .eslintcache 71 | 72 | # Optional REPL history 73 | .node_repl_history 74 | 75 | # Output of 'npm pack' 76 | *.tgz 77 | 78 | # Yarn Integrity file 79 | .yarn-integrity 80 | 81 | # dotenv environment variables file 82 | .env 83 | .env.test 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | 88 | # next.js build output 89 | .next 90 | 91 | # nuxt.js build output 92 | .nuxt 93 | 94 | # rollup.js default build output 95 | dist/ 96 | 97 | # Uncomment the public line if your project uses Gatsby 98 | # https://nextjs.org/blog/next-9-1#public-directory-support 99 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 100 | # public 101 | 102 | # Storybook build outputs 103 | .out 104 | .storybook-out 105 | 106 | # vuepress build output 107 | .vuepress/dist 108 | 109 | # Serverless directories 110 | .serverless/ 111 | 112 | # FuseBox cache 113 | .fusebox/ 114 | 115 | # DynamoDB Local files 116 | .dynamodb/ 117 | 118 | # Temporary folders 119 | tmp/ 120 | temp/ 121 | 122 | # End of https://www.gitignore.io/api/node 123 | 124 | # Created by https://www.gitignore.io/api/macos 125 | # Edit at https://www.gitignore.io/?templates=macos 126 | 127 | ### macOS ### 128 | # General 129 | .DS_Store 130 | .AppleDouble 131 | .LSOverride 132 | 133 | # Icon must end with two \r 134 | Icon 135 | 136 | # Thumbnails 137 | ._* 138 | 139 | # Files that might appear in the root of a volume 140 | .DocumentRevisions-V100 141 | .fseventsd 142 | .Spotlight-V100 143 | .TemporaryItems 144 | .Trashes 145 | .VolumeIcon.icns 146 | .com.apple.timemachine.donotpresent 147 | 148 | # Directories potentially created on remote AFP share 149 | .AppleDB 150 | .AppleDesktop 151 | Network Trash Folder 152 | Temporary Items 153 | .apdisk 154 | 155 | # End of https://www.gitignore.io/api/macos 156 | -------------------------------------------------------------------------------- /napi/build.rs: -------------------------------------------------------------------------------- 1 | extern crate bindgen; 2 | #[cfg(windows)] 3 | extern crate flate2; 4 | extern crate glob; 5 | extern crate napi_build; 6 | #[cfg(windows)] 7 | extern crate reqwest; 8 | extern crate semver; 9 | #[cfg(windows)] 10 | extern crate tar; 11 | 12 | use glob::glob; 13 | 14 | use std::env; 15 | use std::path::PathBuf; 16 | use std::process::Command; 17 | 18 | // https://stackoverflow.com/questions/37498864/finding-executable-in-path-with-rust 19 | 20 | const NODE_PRINT_EXEC_PATH: &'static str = "console.log(process.execPath)"; 21 | 22 | fn main() { 23 | napi_build::setup(); 24 | let node_full_version = 25 | String::from_utf8(Command::new("node").arg("-v").output().unwrap().stdout).unwrap(); 26 | let node_version = semver::Version::parse(node_full_version.as_str().get(1..).unwrap()).unwrap(); 27 | 28 | let node_major_version = node_version.major; 29 | 30 | println!("cargo:rerun-if-env-changed=NODE_INCLUDE_PATH"); 31 | for entry in glob("./src/sys/**/*.*").unwrap() { 32 | println!( 33 | "cargo:rerun-if-changed={}", 34 | entry.unwrap().to_str().unwrap() 35 | ); 36 | } 37 | 38 | if node_major_version < 10 { 39 | panic!("node version is too low") 40 | } 41 | 42 | let node_include_path = find_node_include_path(node_full_version.trim_end()); 43 | 44 | let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); 45 | 46 | let mut sys_bindigs_path = PathBuf::from("src"); 47 | sys_bindigs_path.push("sys"); 48 | sys_bindigs_path.push("bindings.h"); 49 | 50 | bindgen::Builder::default() 51 | .header(sys_bindigs_path.to_str().unwrap().to_owned()) 52 | .clang_arg(String::from("-I") + node_include_path.to_str().unwrap()) 53 | .rustified_enum("(napi_|uv_).+") 54 | .whitelist_function("(napi_|uv_|extras_).+") 55 | .whitelist_type("(napi_|uv_|extras_).+") 56 | .generate() 57 | .expect("Unable to generate napi bindings") 58 | .write_to_file(out_path.join("bindings.rs")) 59 | .expect("Unable to write napi bindings"); 60 | } 61 | 62 | #[cfg(target_os = "windows")] 63 | fn find_node_include_path(node_full_version: &str) -> PathBuf { 64 | let mut node_exec_path = PathBuf::from( 65 | String::from_utf8( 66 | Command::new("node") 67 | .arg("-e") 68 | .arg(NODE_PRINT_EXEC_PATH) 69 | .output() 70 | .unwrap() 71 | .stdout, 72 | ) 73 | .expect("can not find executable node"), 74 | ) 75 | .parent() 76 | .unwrap() 77 | .to_path_buf(); 78 | node_exec_path.push(format!("node-headers-{}.tar.gz", node_full_version)); 79 | let mut header_dist_path = PathBuf::from(&PathBuf::from(&node_exec_path).parent().unwrap()); 80 | let unpack_path = PathBuf::from(&header_dist_path); 81 | header_dist_path.push(format!("node-{}", node_full_version)); 82 | header_dist_path.push("include"); 83 | header_dist_path.push("node"); 84 | if !header_dist_path.exists() { 85 | let header_file_download_url = String::from_utf8( 86 | Command::new("node") 87 | .args(vec!["-e", "console.log(process.release.headersUrl)"]) 88 | .output() 89 | .unwrap() 90 | .stdout, 91 | ) 92 | .unwrap(); 93 | let resp = reqwest::blocking::get(&header_file_download_url).expect("request failed"); 94 | tar::Archive::new(flate2::read::GzDecoder::new(resp)) 95 | .unpack(&unpack_path) 96 | .expect("Unpack headers file failed"); 97 | }; 98 | header_dist_path 99 | } 100 | 101 | #[cfg(not(target_os = "windows"))] 102 | fn find_node_include_path(_node_full_version: &str) -> PathBuf { 103 | let node_exec_path = String::from_utf8( 104 | Command::new("node") 105 | .arg("-e") 106 | .arg(NODE_PRINT_EXEC_PATH) 107 | .output() 108 | .unwrap() 109 | .stdout, 110 | ) 111 | .unwrap(); 112 | PathBuf::from(node_exec_path) 113 | .parent() 114 | .unwrap() 115 | .parent() 116 | .unwrap() 117 | .join("include/node") 118 | } 119 | -------------------------------------------------------------------------------- /napi/src/async_work.rs: -------------------------------------------------------------------------------- 1 | use std::mem; 2 | use std::os::raw::{c_char, c_void}; 3 | use std::ptr; 4 | 5 | use crate::{check_status, sys, Env, Result, Task}; 6 | 7 | pub struct AsyncWork { 8 | inner_task: T, 9 | deferred: sys::napi_deferred, 10 | value: Result<*mut T::Output>, 11 | } 12 | 13 | impl AsyncWork { 14 | pub fn run(env: sys::napi_env, task: T, deferred: sys::napi_deferred) -> Result<()> { 15 | let mut raw_resource = ptr::null_mut(); 16 | let status = unsafe { sys::napi_create_object(env, &mut raw_resource) }; 17 | check_status(status)?; 18 | let mut raw_name = ptr::null_mut(); 19 | let s = "napi_rs_async"; 20 | let status = unsafe { 21 | sys::napi_create_string_utf8( 22 | env, 23 | s.as_ptr() as *const c_char, 24 | s.len() as u64, 25 | &mut raw_name, 26 | ) 27 | }; 28 | check_status(status)?; 29 | let mut raw_context = ptr::null_mut(); 30 | unsafe { 31 | let status = sys::napi_async_init(env, raw_resource, raw_name, &mut raw_context); 32 | check_status(status)?; 33 | }; 34 | let result = AsyncWork { 35 | inner_task: task, 36 | deferred, 37 | value: Ok(ptr::null_mut()), 38 | }; 39 | let mut async_work = ptr::null_mut(); 40 | check_status(unsafe { 41 | sys::napi_create_async_work( 42 | env, 43 | raw_resource, 44 | raw_name, 45 | Some(execute:: as unsafe extern "C" fn(env: sys::napi_env, data: *mut c_void)), 46 | Some( 47 | complete:: 48 | as unsafe extern "C" fn( 49 | env: sys::napi_env, 50 | status: sys::napi_status, 51 | data: *mut c_void, 52 | ), 53 | ), 54 | Box::leak(Box::new(result)) as *mut _ as *mut c_void, 55 | &mut async_work, 56 | ) 57 | })?; 58 | check_status(unsafe { sys::napi_queue_async_work(env, async_work) }) 59 | } 60 | } 61 | 62 | unsafe impl Send for AsyncWork {} 63 | 64 | unsafe impl Sync for AsyncWork {} 65 | 66 | unsafe extern "C" fn execute(_env: sys::napi_env, data: *mut c_void) { 67 | let mut work = Box::from_raw(data as *mut AsyncWork); 68 | work.value = work 69 | .inner_task 70 | .compute() 71 | .map(|v| Box::into_raw(Box::from(v))); 72 | Box::leak(work); 73 | } 74 | 75 | unsafe extern "C" fn complete( 76 | env: sys::napi_env, 77 | status: sys::napi_status, 78 | data: *mut c_void, 79 | ) { 80 | let mut work = Box::from_raw(data as *mut AsyncWork); 81 | let value_ptr = mem::replace(&mut work.value, Ok(ptr::null_mut())); 82 | let deferred = mem::replace(&mut work.deferred, ptr::null_mut()); 83 | let value = value_ptr.and_then(move |v| { 84 | let mut env = Env::from_raw(env); 85 | let output = ptr::read(v as *const _); 86 | work.inner_task.resolve(&mut env, output) 87 | }); 88 | let mut handle_scope = ptr::null_mut(); 89 | match check_status(status).and_then(move |_| value) { 90 | Ok(v) => { 91 | let open_handle_status = sys::napi_open_handle_scope(env, &mut handle_scope); 92 | debug_assert!( 93 | open_handle_status == sys::napi_status::napi_ok, 94 | "OpenHandleScope failed" 95 | ); 96 | let status = sys::napi_resolve_deferred(env, deferred, v.raw_value); 97 | debug_assert!(status == sys::napi_status::napi_ok, "Reject promise failed"); 98 | } 99 | Err(e) => { 100 | let open_handle_status = sys::napi_open_handle_scope(env, &mut handle_scope); 101 | debug_assert!( 102 | open_handle_status == sys::napi_status::napi_ok, 103 | "OpenHandleScope failed" 104 | ); 105 | let status = sys::napi_reject_deferred(env, deferred, e.into_raw(env)); 106 | debug_assert!(status == sys::napi_status::napi_ok, "Reject promise failed"); 107 | } 108 | }; 109 | let close_handle_scope_status = sys::napi_close_handle_scope(env, handle_scope); 110 | debug_assert!( 111 | close_handle_scope_status == sys::napi_status::napi_ok, 112 | "Close handle scope failed" 113 | ); 114 | } 115 | -------------------------------------------------------------------------------- /napi-derive/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate proc_macro; 2 | 3 | use proc_macro::TokenStream; 4 | use proc_macro2::{Ident, Literal}; 5 | use quote::{format_ident, quote}; 6 | use syn::fold::{fold_fn_arg, fold_signature, Fold}; 7 | use syn::parse::{Parse, ParseStream, Result}; 8 | use syn::punctuated::Punctuated; 9 | use syn::{parse_macro_input, Block, FnArg, ItemFn, Signature, Token}; 10 | 11 | struct ArgLength { 12 | length: Option, 13 | } 14 | 15 | impl Parse for ArgLength { 16 | fn parse(input: ParseStream) -> Result { 17 | let vars = Punctuated::::parse_terminated(input)?; 18 | Ok(ArgLength { 19 | length: vars.first().map(|i| i.clone()), 20 | }) 21 | } 22 | } 23 | 24 | struct JsFunction { 25 | args: Vec, 26 | name: Option, 27 | signature: Option, 28 | block: Vec, 29 | } 30 | 31 | impl JsFunction { 32 | pub fn new() -> Self { 33 | JsFunction { 34 | args: vec![], 35 | name: None, 36 | signature: None, 37 | block: vec![], 38 | } 39 | } 40 | } 41 | 42 | impl Fold for JsFunction { 43 | fn fold_fn_arg(&mut self, arg: FnArg) -> FnArg { 44 | self.args.push(arg.clone()); 45 | fold_fn_arg(self, arg) 46 | } 47 | 48 | fn fold_signature(&mut self, signature: Signature) -> Signature { 49 | self.name = Some(format_ident!("{}", signature.ident)); 50 | let mut new_signature = signature.clone(); 51 | new_signature.ident = format_ident!("_{}", signature.ident); 52 | self.signature = Some(new_signature); 53 | fold_signature(self, signature) 54 | } 55 | 56 | fn fold_block(&mut self, node: Block) -> Block { 57 | self.block.push(node.clone()); 58 | node 59 | } 60 | } 61 | 62 | #[proc_macro_attribute] 63 | pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream { 64 | let arg_len = parse_macro_input!(attr as ArgLength); 65 | let arg_len_span = arg_len.length.unwrap_or(Literal::usize_unsuffixed(0)); 66 | let input = parse_macro_input!(input as ItemFn); 67 | let mut js_fn = JsFunction::new(); 68 | js_fn.fold_item_fn(input); 69 | let fn_name = js_fn.name.unwrap(); 70 | let fn_block = js_fn.block; 71 | let signature = js_fn.signature.unwrap(); 72 | let new_fn_name = signature.ident.clone(); 73 | let expanded = quote! { 74 | #signature #(#fn_block)* 75 | 76 | extern "C" fn #fn_name( 77 | raw_env: napi_rs::sys::napi_env, 78 | cb_info: napi_rs::sys::napi_callback_info, 79 | ) -> napi_rs::sys::napi_value { 80 | use std::io::Write; 81 | use std::mem; 82 | use std::os::raw::c_char; 83 | use std::ptr; 84 | use napi_rs::{Any, Env, Status, Value, CallContext}; 85 | let mut argc = #arg_len_span as usize; 86 | let mut raw_args = 87 | unsafe { mem::MaybeUninit::<[napi_rs::sys::napi_value; 8]>::uninit().assume_init() }; 88 | let mut raw_this = ptr::null_mut(); 89 | 90 | let mut has_error = false; 91 | 92 | unsafe { 93 | let status = napi_rs::sys::napi_get_cb_info( 94 | raw_env, 95 | cb_info, 96 | &mut argc as *mut usize as *mut u64, 97 | &mut raw_args[0], 98 | &mut raw_this, 99 | ptr::null_mut(), 100 | ); 101 | has_error = has_error && (Status::from(status) == Status::Ok); 102 | } 103 | 104 | let mut env = Env::from_raw(raw_env); 105 | let call_ctx = CallContext::new(&mut env, raw_this, raw_args, #arg_len_span); 106 | let result = call_ctx.and_then(|ctx| #new_fn_name(ctx)); 107 | has_error = has_error && result.is_err(); 108 | 109 | match result { 110 | Ok(result) => result.into_raw(), 111 | Err(e) => { 112 | let message = format!("{:?}", e); 113 | unsafe { 114 | napi_rs::sys::napi_throw_error(raw_env, ptr::null(), message.as_ptr() as *const c_char); 115 | } 116 | let mut undefined = ptr::null_mut(); 117 | unsafe { napi_rs::sys::napi_get_undefined(raw_env, &mut undefined) }; 118 | undefined 119 | } 120 | } 121 | } 122 | }; 123 | // Hand the output tokens back to the compiler 124 | TokenStream::from(expanded) 125 | } 126 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at lynweklm@gmail.com. 63 | All complaints will be reviewed and investigated promptly and fairly. 64 | 65 | All community leaders are obligated to respect the privacy and security of the 66 | reporter of any incident. 67 | 68 | ## Enforcement Guidelines 69 | 70 | Community leaders will follow these Community Impact Guidelines in determining 71 | the consequences for any action they deem in violation of this Code of Conduct: 72 | 73 | ### 1. Correction 74 | 75 | **Community Impact**: Use of inappropriate language or other behavior deemed 76 | unprofessional or unwelcome in the community. 77 | 78 | **Consequence**: A private, written warning from community leaders, providing 79 | clarity around the nature of the violation and an explanation of why the 80 | behavior was inappropriate. A public apology may be requested. 81 | 82 | ### 2. Warning 83 | 84 | **Community Impact**: A violation through a single incident or series 85 | of actions. 86 | 87 | **Consequence**: A warning with consequences for continued behavior. No 88 | interaction with the people involved, including unsolicited interaction with 89 | those enforcing the Code of Conduct, for a specified period of time. This 90 | includes avoiding interactions in community spaces as well as external channels 91 | like social media. Violating these terms may lead to a temporary or 92 | permanent ban. 93 | 94 | ### 3. Temporary Ban 95 | 96 | **Community Impact**: A serious violation of community standards, including 97 | sustained inappropriate behavior. 98 | 99 | **Consequence**: A temporary ban from any sort of interaction or public 100 | communication with the community for a specified period of time. No public or 101 | private interaction with the people involved, including unsolicited interaction 102 | with those enforcing the Code of Conduct, is allowed during this period. 103 | Violating these terms may lead to a permanent ban. 104 | 105 | ### 4. Permanent Ban 106 | 107 | **Community Impact**: Demonstrating a pattern of violation of community 108 | standards, including sustained inappropriate behavior, harassment of an 109 | individual, or aggression toward or disparagement of classes of individuals. 110 | 111 | **Consequence**: A permanent ban from any sort of public interaction within 112 | the community. 113 | 114 | ## Attribution 115 | 116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 117 | version 2.0, available at 118 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 119 | 120 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 121 | enforcement ladder](https://github.com/mozilla/diversity). 122 | 123 | [homepage]: https://www.contributor-covenant.org 124 | 125 | For answers to common questions about this code of conduct, see the FAQ at 126 | https://www.contributor-covenant.org/faq. Translations are available at 127 | https://www.contributor-covenant.org/translations. 128 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # napi-rs 2 | 3 | > This project was initialized from [xray](https://github.com/atom/xray) 4 | 5 | # Platform Support 6 | 7 | ![](https://github.com/Brooooooklyn/napi-rs/workflows/macOS/badge.svg) 8 | ![](https://github.com/Brooooooklyn/napi-rs/workflows/Linux/badge.svg) 9 | ![](https://github.com/Brooooooklyn/napi-rs/workflows/Windows/badge.svg) 10 | 11 | ## Operating Systems 12 | 13 | | Linux | macOS | Windows x64 MSVC | 14 | | ----- | ----- | ---------------- | 15 | | ✓ | ✓ | ✓ | 16 | 17 | ## NodeJS 18 | 19 | | Node10 | Node 12 | Node13 | Node14 | 20 | | ------ | ------- | ------ | ------ | 21 | | ✓ | ✓ | ✓ | ✓ | 22 | 23 | A minimal library for building compiled Node add-ons in Rust. 24 | 25 | This library depends on N-API and requires Node 8.9 or later. It is still pretty raw and has not been tested in a production setting. 26 | 27 | One nice feature is that this crate allows you to build add-ons purely with the Rust toolchain and without involving `node-gyp`. 28 | 29 | ## Taste 30 | 31 | ```rust 32 | #[js_function(1)] // ------> arguments length, omit for zero 33 | fn fibonacci(ctx: CallContext) -> Result> { 34 | let n = ctx.get::(0)?.try_into()?; 35 | ctx.env.create_int64(fibonacci_native(n)) 36 | } 37 | 38 | #[inline] 39 | fn fibonacci_native(n: i64) -> i64 { 40 | match n { 41 | 1 | 2 => 1, 42 | _ => fibonacci_native(n - 1) + fibonacci_native(n - 2), 43 | } 44 | } 45 | ``` 46 | 47 | ## Building 48 | 49 | This repository is a Cargo crate. Any napi-based add-on should contain `Cargo.toml` to make it a Cargo crate. 50 | 51 | In your `Cargo.toml` you need to set the `crate-type` to `"cdylib"` so that cargo builds a C-style shared library that can be dynamically loaded by the Node executable. You'll also need to add this crate as a dependency. 52 | 53 | ```toml 54 | [lib] 55 | crate-type = ["cdylib"] 56 | 57 | [dependencies] 58 | napi-rs = "0.1" 59 | 60 | [build-dependencies] 61 | napi-build = "0.1" 62 | ``` 63 | 64 | And create `build.rs` in your own project: 65 | 66 | ```rust 67 | // build.rs 68 | extern crate napi_build; 69 | 70 | fn main() { 71 | napi_build::setup(); 72 | } 73 | ``` 74 | 75 | So far, the `napi` build script has only been tested on `macOS` `Linux` and `Windows x64 MSVC`. 76 | 77 | See the included [test_module](./test_module) for an example add-on. 78 | 79 | Run `cargo build` to produce the `Dynamic lib` file. And install the `napi-rs` to help you copy `Dynamic lib` file to `.node` file in case you can `require` it in your program. 80 | 81 | ```json 82 | { 83 | "package": "your pkg", 84 | "dependencies": { 85 | "napi-rs": "^0.1" 86 | }, 87 | "scripts": { 88 | "build": "cargo build && napi", 89 | "build-release": "cargo build --release && napi --release" 90 | } 91 | } 92 | ``` 93 | 94 | Then you can require your native binding: 95 | 96 | ```js 97 | require('./target/debug|release/[module_name].node') 98 | ``` 99 | 100 | The `module_name` would be your `package` name in your `Cargo.toml`. 101 | 102 | `xxx => ./target/debug|release/xxx.node` 103 | 104 | `xxx-yyy => ./target/debug|release/xxx_yyy.node` 105 | 106 | You can also copy `Dynamic lib` file to an appointed location: 107 | 108 | ```bash 109 | napi [--release] . 110 | napi [--release] ./mylib 111 | napi [--release] ./mylib.node 112 | ``` 113 | 114 | ## Testing 115 | 116 | Because libraries that depend on this crate must be loaded into a Node executable in order to resolve symbols, all tests are written in JavaScript in the `test_module` subdirectory. 117 | 118 | To run tests: 119 | 120 | ```sh 121 | cd test_module 122 | npm run build 123 | npm test 124 | ``` 125 | 126 | ## Features table 127 | 128 | ### Create JavaScript values 129 | 130 | | NAPI | NAPI Version | Minimal Node version | Status | 131 | | ------------------------------------------------------------------------------------------------------------ | ------------ | -------------------- | ------ | 132 | | [Enum types](https://nodejs.org/api/n-api.html#n_api_enum_types) | 6 | v13.7.0 | ⛔️ | 133 | | [napi_create_array](https://nodejs.org/api/n-api.html#n_api_napi_create_array) | 1 | v8.0.0 | ✅ | 134 | | [napi_create_array_with_length](https://nodejs.org/api/n-api.html#n_api_napi_create_array_with_length) | 1 | v8.0.0 | ✅ | 135 | | [napi_create_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_arraybuffer) | 1 | v8.0.0 | ✅ | 136 | | [napi_create_buffer](https://nodejs.org/api/n-api.html#n_api_napi_create_buffer) | 1 | v8.0.0 | ✅ | 137 | | [napi_create_buffer_copy](https://nodejs.org/api/n-api.html#n_api_napi_create_buffer_copy) | 1 | v8.0.0 | ⛔️ | 138 | | [napi_create_date](https://nodejs.org/api/n-api.html#n_api_napi_create_date) | 5 | v11.11.0 | ⛔️ | 139 | | [napi_create_external](https://nodejs.org/api/n-api.html#n_api_napi_create_external) | 1 | v8.0.0 | ⛔️ | 140 | | [napi_create_external_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_arraybuffer) | 1 | v8.0.0 | ✅ | 141 | | [napi_create_external_buffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_buffer) | 1 | v8.0.0 | ✅ | 142 | | [napi_create_object](https://nodejs.org/api/n-api.html#n_api_napi_create_object) | 1 | v8.0.0 | ✅ | 143 | | [napi_create_symbol](https://nodejs.org/api/n-api.html#n_api_napi_create_symbol) | 1 | v8.0.0 | ⛔️ | 144 | | [napi_create_typedarray](https://nodejs.org/api/n-api.html#n_api_napi_create_typedarray) | 1 | v8.0.0 | ⛔️ | 145 | | [napi_create_dataview](https://nodejs.org/api/n-api.html#n_api_napi_create_dataview) | 1 | v8.3.0 | ⛔️ | 146 | | [napi_create_int32](https://nodejs.org/api/n-api.html#n_api_napi_create_int32) | 1 | v8.4.0 | ✅ | 147 | | [napi_create_uint32](https://nodejs.org/api/n-api.html#n_api_napi_create_uint32) | 1 | v8.4.0 | ✅ | 148 | | [napi_create_int64](https://nodejs.org/api/n-api.html#n_api_napi_create_int64) | 1 | v8.4.0 | ✅ | 149 | | [napi_create_double](https://nodejs.org/api/n-api.html#n_api_napi_create_double) | 1 | v8.4.0 | ✅ | 150 | | [napi_create_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_int64) | 6 | v10.7.0 | ⛔️ | 151 | | [napi_create_bigint_uint64](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_uint64) | 6 | v10.7.0 | ⛔️ | 152 | | [napi_create_bigint_words](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_words) | 6 | v10.7.0 | ⛔️ | 153 | | [napi_create_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_create_string_latin1) | 1 | v8.0.0 | ⛔️ | 154 | | [napi_create_string_utf16](https://nodejs.org/api/n-api.html#n_api_napi_create_string_utf16) | 1 | v8.0.0 | ✅ | 155 | | [napi_create_string_utf8](https://nodejs.org/api/n-api.html#n_api_napi_create_string_utf8) | 1 | v8.0.0 | ✅ | 156 | 157 | ### [Functions to convert from N-API to C types](https://nodejs.org/api/n-api.html#n_api_functions_to_convert_from_n_api_to_c_types) 158 | 159 | | NAPI | NAPI Version | Minimal Node Version | Status | 160 | | ---------------------------------------------------------------------------------------------------- | ------------ | -------------------- | ------ | 161 | | [napi_get_array_length](https://nodejs.org/api/n-api.html#n_api_napi_get_array_length) | 1 | v8.0.0 | ✅ | 162 | | [napi_get_arraybuffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_arraybuffer_info) | 1 | v8.0.0 | ✅ | 163 | | [napi_get_buffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_buffer_info) | 1 | v8.0.0 | ✅ | 164 | | [napi_get_prototype](https://nodejs.org/api/n-api.html#n_api_napi_get_prototype) | 1 | v8.0.0 | ⛔️ | 165 | | [napi_get_typedarray_info](https://nodejs.org/api/n-api.html#n_api_napi_get_typedarray_info) | 1 | v8.0.0 | ⛔️ | 166 | | [napi_get_dataview_info](https://nodejs.org/api/n-api.html#n_api_napi_get_dataview_info) | 1 | v8.3.0 | ⛔️ | 167 | | [napi_get_date_value](https://nodejs.org/api/n-api.html#n_api_napi_get_date_value) | 5 | v11.11.0 | ⛔️ | 168 | | [napi_get_value_bool](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bool) | 1 | v8.0.0 | ✅ | 169 | | [napi_get_value_double](https://nodejs.org/api/n-api.html#n_api_napi_get_value_double) | 1 | v8.0.0 | ✅ | 170 | | [napi_get_value_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_int64) | 6 | v10.7.0 | ⛔️ | 171 | | [napi_get_value_bigint_uint64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_uint64) | 6 | v10.7.0 | ⛔️ | 172 | | [napi_get_value_bigint_words](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_words) | 6 | v10.7.0 | ⛔️ | 173 | | [napi_get_value_external](https://nodejs.org/api/n-api.html#n_api_napi_get_value_external) | 1 | v8.0.0 | ⛔️ | 174 | | [napi_get_value_int32](https://nodejs.org/api/n-api.html#n_api_napi_get_value_int32) | 1 | v8.0.0 | ✅ | 175 | | [napi_get_value_int64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_int64) | 1 | v8.0.0 | ✅ | 176 | | [napi_get_value_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_latin1) | 1 | v8.0.0 | ⛔️ | 177 | | [napi_get_value_string_utf8](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_utf8) | 1 | v8.0.0 | ✅ | 178 | | [napi_get_value_string_utf16](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_utf16) | 1 | v8.0.0 | ✅ | 179 | | [napi_get_value_uint32](https://nodejs.org/api/n-api.html#n_api_napi_get_value_uint32) | 1 | v8.0.0 | ✅ | 180 | | [napi_get_boolean](https://nodejs.org/api/n-api.html#n_api_napi_get_boolean) | 1 | v8.0.0 | ✅ | 181 | | [napi_get_global](https://nodejs.org/api/n-api.html#n_api_napi_get_global) | 1 | v8.0.0 | ⛔️ | 182 | | [napi_get_null](https://nodejs.org/api/n-api.html#n_api_napi_get_null) | 1 | v8.0.0 | ✅ | 183 | | [napi_get_undefined](https://nodejs.org/api/n-api.html#n_api_napi_get_undefined) | 1 | v8.0.0 | ✅ | 184 | 185 | ### [Working with JavaScript Values and Abstract Operations](https://nodejs.org/api/n-api.html#n_api_working_with_javascript_values_and_abstract_operations) 186 | 187 | | NAPI | NAPI Version | Minimal Node Version | Status | 188 | | ---------------------------------------------------------------------------------------------------- | ------------ | -------------------- | ------ | 189 | | [napi_coerce_to_bool](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_bool) | 1 | v8.0.0 | ✅ | 190 | | [napi_coerce_to_number](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_number) | 1 | v8.0.0 | ✅ | 191 | | [napi_coerce_to_object](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_object) | 1 | v8.0.0 | ✅ | 192 | | [napi_coerce_to_string](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_string) | 1 | v8.0.0 | ✅ | 193 | | [napi_typeof](https://nodejs.org/api/n-api.html#n_api_napi_typeof) | 1 | v8.0.0 | ✅ | 194 | | [napi_instanceof](https://nodejs.org/api/n-api.html#n_api_napi_instanceof) | 1 | v8.0.0 | ⛔️ | 195 | | [napi_is_array](https://nodejs.org/api/n-api.html#n_api_napi_is_array) | 1 | v8.0.0 | ✅ | 196 | | [napi_is_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_is_arraybuffer) | 1 | v8.0.0 | ✅ | 197 | | [napi_is_buffer](https://nodejs.org/api/n-api.html#n_api_napi_is_buffer) | 1 | v8.0.0 | ✅ | 198 | | [napi_is_date](https://nodejs.org/api/n-api.html#n_api_napi_is_date) | 1 | v8.0.0 | ⛔️ | 199 | | [napi_is_error](https://nodejs.org/api/n-api.html#n_api_napi_is_error_1) | 1 | v8.0.0 | ⛔️ | 200 | | [napi_is_typedarray](https://nodejs.org/api/n-api.html#n_api_napi_is_typedarray) | 1 | v8.0.0 | ⛔️ | 201 | | [napi_is_dataview](https://nodejs.org/api/n-api.html#n_api_napi_is_dataview) | 1 | v8.3.0 | ⛔️ | 202 | | [napi_strict_equals](https://nodejs.org/api/n-api.html#n_api_napi_strict_equals) | 1 | v8.0.0 | ⛔️ | 203 | | [napi_detach_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_detach_arraybuffer) | Experimental | v13.3.0 | ⛔️ | 204 | | [napi_is_detached_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_is_detached_arraybuffer) | Experimental | v13.3.0 | ⛔️ | 205 | -------------------------------------------------------------------------------- /napi/src/lib.rs: -------------------------------------------------------------------------------- 1 | use async_work::AsyncWork; 2 | use core::fmt::Debug; 3 | use std::any::TypeId; 4 | use std::convert::{TryFrom, TryInto}; 5 | use std::ffi::CString; 6 | use std::marker::PhantomData; 7 | use std::mem; 8 | use std::ops::{Deref, DerefMut}; 9 | use std::os::raw::{c_char, c_void}; 10 | use std::ptr; 11 | use std::slice; 12 | use std::str; 13 | use std::string::String as RustString; 14 | 15 | mod async_work; 16 | mod call_context; 17 | pub mod sys; 18 | mod task; 19 | mod version; 20 | 21 | pub use call_context::CallContext; 22 | pub use sys::{napi_valuetype, Status}; 23 | pub use task::Task; 24 | pub use version::NodeVersion; 25 | 26 | pub type Result = std::result::Result; 27 | pub type Callback = extern "C" fn(sys::napi_env, sys::napi_callback_info) -> sys::napi_value; 28 | 29 | #[derive(Debug, Clone)] 30 | pub struct Error { 31 | pub status: Status, 32 | pub reason: Option, 33 | } 34 | 35 | #[derive(Clone, Copy, Debug)] 36 | pub struct Env(sys::napi_env); 37 | 38 | // Value types 39 | #[derive(Clone, Copy, Debug)] 40 | pub struct Any; 41 | 42 | #[derive(Clone, Copy, Debug)] 43 | pub struct Undefined; 44 | 45 | #[derive(Clone, Copy, Debug)] 46 | pub struct Null; 47 | 48 | #[derive(Clone, Copy, Debug)] 49 | pub struct Boolean { 50 | value: bool, 51 | } 52 | 53 | #[derive(Clone, Copy, Debug)] 54 | pub enum Number { 55 | Int(i64), 56 | Int32(i32), 57 | U32(u32), 58 | Double(f64), 59 | } 60 | 61 | #[derive(Clone, Copy, Debug)] 62 | pub struct JsString; 63 | 64 | #[derive(Clone, Copy, Debug)] 65 | pub struct Object; 66 | 67 | #[derive(Clone, Copy, Debug)] 68 | pub struct Function; 69 | 70 | #[derive(Clone, Copy, Debug)] 71 | pub struct Buffer { 72 | data: *const u8, 73 | size: u64, 74 | } 75 | 76 | #[derive(Clone, Copy, Debug)] 77 | pub struct ArrayBuffer { 78 | data: *const u8, 79 | size: u64, 80 | } 81 | 82 | #[derive(Clone, Copy, Debug)] 83 | pub struct Value { 84 | env: sys::napi_env, 85 | raw_value: sys::napi_value, 86 | value: T, 87 | } 88 | 89 | pub struct Ref { 90 | raw_env: sys::napi_env, 91 | raw_ref: sys::napi_ref, 92 | _marker: PhantomData, 93 | } 94 | 95 | #[derive(Clone, Debug)] 96 | pub struct Property { 97 | name: RustString, 98 | raw_descriptor: sys::napi_property_descriptor, 99 | } 100 | 101 | #[repr(C)] 102 | struct TaggedObject { 103 | type_id: TypeId, 104 | object: Option, 105 | } 106 | 107 | #[macro_export] 108 | macro_rules! register_module { 109 | ($module_name:ident, $init:ident) => { 110 | #[no_mangle] 111 | #[cfg_attr(target_os = "linux", link_section = ".ctors")] 112 | #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")] 113 | #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] 114 | pub static __REGISTER_MODULE: extern "C" fn() = { 115 | use std::io::Write; 116 | use std::os::raw::c_char; 117 | use std::ptr; 118 | use $crate::sys; 119 | 120 | extern "C" fn register_module() { 121 | static mut MODULE_DESCRIPTOR: Option = None; 122 | unsafe { 123 | MODULE_DESCRIPTOR = Some(sys::napi_module { 124 | nm_version: 1, 125 | nm_flags: 0, 126 | nm_filename: concat!(file!(), "\0").as_ptr() as *const c_char, 127 | nm_register_func: Some(init_module), 128 | nm_modname: concat!(stringify!($module_name), "\0").as_ptr() as *const c_char, 129 | nm_priv: 0 as *mut _, 130 | reserved: [0 as *mut _; 4], 131 | }); 132 | 133 | sys::napi_module_register(MODULE_DESCRIPTOR.as_mut().unwrap() as *mut sys::napi_module); 134 | } 135 | 136 | extern "C" fn init_module( 137 | raw_env: sys::napi_env, 138 | raw_exports: sys::napi_value, 139 | ) -> sys::napi_value { 140 | let env = Env::from_raw(raw_env); 141 | let mut exports: Value = Value::from_raw(raw_env, raw_exports).unwrap(); 142 | 143 | let result = $init(&env, &mut exports); 144 | 145 | match result { 146 | Ok(_) => exports.into_raw(), 147 | Err(e) => { 148 | unsafe { 149 | sys::napi_throw_error( 150 | raw_env, 151 | ptr::null(), 152 | format!("Error initializing module: {:?}", e).as_ptr() as *const _, 153 | ) 154 | }; 155 | ptr::null_mut() 156 | } 157 | } 158 | } 159 | } 160 | 161 | register_module 162 | }; 163 | }; 164 | } 165 | 166 | impl Error { 167 | pub fn from_status(status: Status) -> Self { 168 | Error { 169 | status: status, 170 | reason: None, 171 | } 172 | } 173 | 174 | pub fn into_raw(self, env: sys::napi_env) -> sys::napi_value { 175 | let mut err = ptr::null_mut(); 176 | let s = self.reason.unwrap_or("NAPI error".to_owned()); 177 | unsafe { 178 | let mut err_reason = ptr::null_mut(); 179 | let status = sys::napi_create_string_utf8( 180 | env, 181 | s.as_ptr() as *const c_char, 182 | s.len() as u64, 183 | &mut err_reason, 184 | ); 185 | debug_assert!( 186 | status == sys::napi_status::napi_ok, 187 | "Create error reason failed" 188 | ); 189 | let status = sys::napi_create_error(env, ptr::null_mut(), err_reason, &mut err); 190 | debug_assert!(status == sys::napi_status::napi_ok, "Create error failed"); 191 | }; 192 | err 193 | } 194 | } 195 | 196 | impl From for Error { 197 | fn from(error: std::ffi::NulError) -> Self { 198 | Error { 199 | status: Status::StringExpected, 200 | reason: Some(format!("{:?}", error)), 201 | } 202 | } 203 | } 204 | 205 | impl Env { 206 | pub fn from_raw(env: sys::napi_env) -> Self { 207 | Env(env) 208 | } 209 | 210 | pub fn get_undefined(&self) -> Result> { 211 | let mut raw_value = ptr::null_mut(); 212 | let status = unsafe { sys::napi_get_undefined(self.0, &mut raw_value) }; 213 | check_status(status)?; 214 | Ok(Value::from_raw_value(self, raw_value, Undefined)) 215 | } 216 | 217 | pub fn get_null(&self) -> Result> { 218 | let mut raw_value = ptr::null_mut(); 219 | let status = unsafe { sys::napi_get_null(self.0, &mut raw_value) }; 220 | check_status(status)?; 221 | Ok(Value::from_raw_value(self, raw_value, Null)) 222 | } 223 | 224 | pub fn get_boolean(&self, value: bool) -> Result> { 225 | let mut raw_value = ptr::null_mut(); 226 | let status = unsafe { sys::napi_get_boolean(self.0, value, &mut raw_value) }; 227 | check_status(status)?; 228 | Ok(Value::from_raw_value(self, raw_value, Boolean { value })) 229 | } 230 | 231 | pub fn create_int32(&self, int: i32) -> Result> { 232 | let mut raw_value = ptr::null_mut(); 233 | let status = 234 | unsafe { sys::napi_create_int32(self.0, int, (&mut raw_value) as *mut sys::napi_value) }; 235 | check_status(status)?; 236 | Ok(Value::from_raw_value(self, raw_value, Number::Int32(int))) 237 | } 238 | 239 | pub fn create_int64(&self, int: i64) -> Result> { 240 | let mut raw_value = ptr::null_mut(); 241 | let status = 242 | unsafe { sys::napi_create_int64(self.0, int, (&mut raw_value) as *mut sys::napi_value) }; 243 | check_status(status)?; 244 | Ok(Value::from_raw_value(self, raw_value, Number::Int(int))) 245 | } 246 | 247 | pub fn create_uint32(&self, number: u32) -> Result> { 248 | let mut raw_value = ptr::null_mut(); 249 | let status = unsafe { sys::napi_create_uint32(self.0, number, &mut raw_value) }; 250 | check_status(status)?; 251 | Ok(Value::from_raw_value(self, raw_value, Number::U32(number))) 252 | } 253 | 254 | pub fn create_double(&self, double: f64) -> Result> { 255 | let mut raw_value = ptr::null_mut(); 256 | let status = 257 | unsafe { sys::napi_create_double(self.0, double, (&mut raw_value) as *mut sys::napi_value) }; 258 | check_status(status)?; 259 | Ok(Value::from_raw_value( 260 | self, 261 | raw_value, 262 | Number::Double(double), 263 | )) 264 | } 265 | 266 | pub fn create_string<'a, 'b>(&'a self, s: &'b str) -> Result> { 267 | let mut raw_value = ptr::null_mut(); 268 | let status = unsafe { 269 | sys::napi_create_string_utf8( 270 | self.0, 271 | s.as_ptr() as *const c_char, 272 | s.len() as u64, 273 | &mut raw_value, 274 | ) 275 | }; 276 | check_status(status)?; 277 | Ok(Value::from_raw_value(self, raw_value, JsString)) 278 | } 279 | 280 | pub fn create_string_utf16(&self, chars: &[u16]) -> Result> { 281 | let mut raw_value = ptr::null_mut(); 282 | let status = unsafe { 283 | sys::napi_create_string_utf16(self.0, chars.as_ptr(), chars.len() as u64, &mut raw_value) 284 | }; 285 | check_status(status)?; 286 | Ok(Value::from_raw_value(self, raw_value, JsString)) 287 | } 288 | 289 | pub fn create_object(&self) -> Result> { 290 | let mut raw_value = ptr::null_mut(); 291 | let status = unsafe { sys::napi_create_object(self.0, &mut raw_value) }; 292 | check_status(status)?; 293 | Ok(Value::from_raw_value(self, raw_value, Object)) 294 | } 295 | 296 | pub fn create_array_with_length(&self, length: usize) -> Result> { 297 | let mut raw_value = ptr::null_mut(); 298 | let status = 299 | unsafe { sys::napi_create_array_with_length(self.0, length as u64, &mut raw_value) }; 300 | check_status(status)?; 301 | Ok(Value::from_raw_value(self, raw_value, Object)) 302 | } 303 | 304 | pub fn create_buffer(&self, length: u64) -> Result> { 305 | let mut raw_value = ptr::null_mut(); 306 | let mut data = ptr::null_mut(); 307 | let status = unsafe { sys::napi_create_buffer(self.0, length, &mut data, &mut raw_value) }; 308 | check_status(status)?; 309 | Ok(Value::from_raw_value( 310 | self, 311 | raw_value, 312 | Buffer { 313 | data: data as *const u8, 314 | size: length, 315 | }, 316 | )) 317 | } 318 | 319 | pub fn create_buffer_with_data(&self, data: Vec) -> Result> { 320 | let length = data.len() as u64; 321 | let mut raw_value = ptr::null_mut(); 322 | let data_ptr = data.as_ptr(); 323 | let status = unsafe { 324 | sys::napi_create_external_buffer( 325 | self.0, 326 | length, 327 | data_ptr as *mut c_void, 328 | Some(drop_buffer), 329 | Box::into_raw(Box::from(length)) as *mut c_void, 330 | &mut raw_value, 331 | ) 332 | }; 333 | check_status(status)?; 334 | let mut changed = 0; 335 | let ajust_external_memory_status = 336 | unsafe { sys::napi_adjust_external_memory(self.0, length as i64, &mut changed) }; 337 | check_status(ajust_external_memory_status)?; 338 | mem::forget(data); 339 | Ok(Value::from_raw_value( 340 | self, 341 | raw_value, 342 | Buffer { 343 | data: data_ptr, 344 | size: length, 345 | }, 346 | )) 347 | } 348 | 349 | pub fn create_arraybuffer(&self, length: u64) -> Result> { 350 | let mut raw_value = ptr::null_mut(); 351 | let mut data = ptr::null_mut(); 352 | let status = unsafe { sys::napi_create_arraybuffer(self.0, length, &mut data, &mut raw_value) }; 353 | check_status(status)?; 354 | Ok(Value::from_raw_value( 355 | self, 356 | raw_value, 357 | ArrayBuffer { 358 | data: data as *const u8, 359 | size: length, 360 | }, 361 | )) 362 | } 363 | 364 | pub fn create_arraybuffer_with_data(&self, data: Vec) -> Result> { 365 | let length = data.len() as u64; 366 | let mut raw_value = ptr::null_mut(); 367 | let data_ptr = data.as_ptr(); 368 | let status = unsafe { 369 | sys::napi_create_external_arraybuffer( 370 | self.0, 371 | data_ptr as *mut c_void, 372 | length, 373 | Some(drop_buffer), 374 | Box::into_raw(Box::from(length)) as *mut c_void, 375 | &mut raw_value, 376 | ) 377 | }; 378 | check_status(status)?; 379 | let mut changed = 0; 380 | let ajust_external_memory_status = 381 | unsafe { sys::napi_adjust_external_memory(self.0, length as i64, &mut changed) }; 382 | check_status(ajust_external_memory_status)?; 383 | mem::forget(data); 384 | Ok(Value::from_raw_value( 385 | self, 386 | raw_value, 387 | ArrayBuffer { 388 | data: data_ptr, 389 | size: length, 390 | }, 391 | )) 392 | } 393 | 394 | pub fn create_function(&self, name: &str, callback: Callback) -> Result> { 395 | let mut raw_result = ptr::null_mut(); 396 | let status = unsafe { 397 | sys::napi_create_function( 398 | self.0, 399 | name.as_ptr() as *const c_char, 400 | name.len() as u64, 401 | Some(callback), 402 | callback as *mut c_void, 403 | &mut raw_result, 404 | ) 405 | }; 406 | 407 | check_status(status)?; 408 | 409 | Ok(Value::from_raw_value(self, raw_result, Function)) 410 | } 411 | 412 | pub fn throw_error(&self, msg: &str) -> Result<()> { 413 | let status = unsafe { sys::napi_throw_error(self.0, ptr::null(), msg.as_ptr() as *const _) }; 414 | check_status(status)?; 415 | Ok(()) 416 | } 417 | 418 | pub fn create_reference(&self, value: &Value) -> Result> { 419 | let mut raw_ref = ptr::null_mut(); 420 | unsafe { 421 | let status = sys::napi_create_reference(self.0, value.raw_value, 1, &mut raw_ref); 422 | check_status(status)?; 423 | }; 424 | 425 | Ok(Ref { 426 | raw_env: self.0, 427 | raw_ref, 428 | _marker: PhantomData, 429 | }) 430 | } 431 | 432 | pub fn get_reference_value(&self, reference: &Ref) -> Result> { 433 | let mut raw_value = ptr::null_mut(); 434 | unsafe { 435 | let status = sys::napi_get_reference_value(self.0, reference.raw_ref, &mut raw_value); 436 | check_status(status)?; 437 | }; 438 | 439 | Value::from_raw(self.0, raw_value) 440 | } 441 | 442 | pub fn define_class<'a, 'b>( 443 | &'a self, 444 | name: &'b str, 445 | constructor_cb: Callback, 446 | properties: Vec, 447 | ) -> Result> { 448 | let mut raw_result = ptr::null_mut(); 449 | let raw_properties = properties 450 | .into_iter() 451 | .map(|prop| prop.into_raw(self)) 452 | .collect::>>()?; 453 | 454 | let status = unsafe { 455 | sys::napi_define_class( 456 | self.0, 457 | name.as_ptr() as *const c_char, 458 | name.len() as u64, 459 | Some(constructor_cb), 460 | ptr::null_mut(), 461 | raw_properties.len() as u64, 462 | raw_properties.as_ptr(), 463 | &mut raw_result, 464 | ) 465 | }; 466 | 467 | check_status(status)?; 468 | 469 | Ok(Value::from_raw_value(self, raw_result, Function)) 470 | } 471 | 472 | pub fn wrap(&self, js_object: &mut Value, native_object: T) -> Result<()> { 473 | let status = unsafe { 474 | sys::napi_wrap( 475 | self.0, 476 | js_object.raw_value, 477 | Box::into_raw(Box::new(TaggedObject::new(native_object))) as *mut c_void, 478 | Some(raw_finalize::), 479 | ptr::null_mut(), 480 | ptr::null_mut(), 481 | ) 482 | }; 483 | 484 | check_status(status).or(Ok(())) 485 | } 486 | 487 | pub fn unwrap(&self, js_object: &Value) -> Result<&mut T> { 488 | unsafe { 489 | let mut unknown_tagged_object: *mut c_void = ptr::null_mut(); 490 | let status = sys::napi_unwrap(self.0, js_object.raw_value, &mut unknown_tagged_object); 491 | check_status(status)?; 492 | 493 | let type_id: *const TypeId = mem::transmute(unknown_tagged_object); 494 | if *type_id == TypeId::of::() { 495 | let tagged_object: *mut TaggedObject = mem::transmute(unknown_tagged_object); 496 | (*tagged_object).object.as_mut().ok_or(Error { 497 | status: Status::InvalidArg, 498 | reason: Some("Invalid argument, nothing attach to js_object".to_owned()), 499 | }) 500 | } else { 501 | Err(Error { 502 | status: Status::InvalidArg, 503 | reason: Some( 504 | "Invalid argument, T on unrwap is not the type of wrapped object".to_owned(), 505 | ), 506 | }) 507 | } 508 | } 509 | } 510 | 511 | pub fn drop_wrapped(&self, js_object: Value) -> Result<()> { 512 | unsafe { 513 | let mut unknown_tagged_object: *mut c_void = ptr::null_mut(); 514 | let status = sys::napi_unwrap(self.0, js_object.raw_value, &mut unknown_tagged_object); 515 | check_status(status)?; 516 | 517 | let type_id: *const TypeId = mem::transmute(unknown_tagged_object); 518 | if *type_id == TypeId::of::() { 519 | let tagged_object: *mut TaggedObject = mem::transmute(unknown_tagged_object); 520 | (*tagged_object).object = None; 521 | Ok(()) 522 | } else { 523 | Err(Error { 524 | status: Status::InvalidArg, 525 | reason: Some( 526 | "Invalid argument, T on drop_wrapped is not the type of wrapped object".to_owned(), 527 | ), 528 | }) 529 | } 530 | } 531 | } 532 | 533 | pub fn create_error(&self, e: Error) -> Result> { 534 | let reason = e.reason.unwrap_or("".to_owned()); 535 | let reason_string = self.create_string(reason.as_str())?; 536 | let mut result = ptr::null_mut(); 537 | let status = unsafe { 538 | sys::napi_create_error( 539 | self.0, 540 | ptr::null_mut(), 541 | reason_string.into_raw(), 542 | &mut result, 543 | ) 544 | }; 545 | check_status(status)?; 546 | Ok(Value::from_raw_value(self, result, Object)) 547 | } 548 | 549 | pub fn spawn(&self, task: T) -> Result> { 550 | let mut raw_promise = ptr::null_mut(); 551 | let mut raw_deferred = ptr::null_mut(); 552 | 553 | check_status(unsafe { sys::napi_create_promise(self.0, &mut raw_deferred, &mut raw_promise) })?; 554 | AsyncWork::run(self.0, task, raw_deferred)?; 555 | Ok(Value::from_raw_value(self, raw_promise, Object)) 556 | } 557 | 558 | pub fn get_node_version(&self) -> Result { 559 | let mut result = ptr::null(); 560 | check_status(unsafe { sys::napi_get_node_version(self.0, &mut result) })?; 561 | let version = unsafe { *result }; 562 | version.try_into() 563 | } 564 | } 565 | 566 | pub trait ValueType: Copy + Debug { 567 | fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result; 568 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result; 569 | } 570 | 571 | impl ValueType for Any { 572 | fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result { 573 | Ok(Any) 574 | } 575 | 576 | fn matches_raw_type(_env: sys::napi_env, _raw: sys::napi_value) -> Result { 577 | Ok(true) 578 | } 579 | } 580 | 581 | impl ValueType for Undefined { 582 | fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result { 583 | Ok(Undefined) 584 | } 585 | 586 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 587 | Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_undefined) 588 | } 589 | } 590 | 591 | impl ValueType for Null { 592 | fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result { 593 | Ok(Null) 594 | } 595 | 596 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 597 | Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_null) 598 | } 599 | } 600 | 601 | impl ValueType for Boolean { 602 | fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result { 603 | let mut value = true; 604 | let status = unsafe { sys::napi_get_value_bool(env, raw, &mut value) }; 605 | check_status(status)?; 606 | Ok(Boolean { value }) 607 | } 608 | 609 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 610 | Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_boolean) 611 | } 612 | } 613 | 614 | impl ValueType for Number { 615 | fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result { 616 | let mut double: f64 = 0.0; 617 | let status = unsafe { sys::napi_get_value_double(env, raw, &mut double) }; 618 | check_status(status)?; 619 | Ok(Number::Double(double)) 620 | } 621 | 622 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 623 | Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_number) 624 | } 625 | } 626 | 627 | impl ValueType for JsString { 628 | fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result { 629 | Ok(JsString {}) 630 | } 631 | 632 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 633 | Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_string) 634 | } 635 | } 636 | 637 | impl ValueType for Object { 638 | fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result { 639 | Ok(Object {}) 640 | } 641 | 642 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 643 | Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_object) 644 | } 645 | } 646 | 647 | impl ValueType for Buffer { 648 | fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result { 649 | let mut data = ptr::null_mut(); 650 | let mut size: u64 = 0; 651 | let status = unsafe { sys::napi_get_buffer_info(env, raw, &mut data, &mut size) }; 652 | check_status(status)?; 653 | Ok(Buffer { 654 | data: data as *const u8, 655 | size, 656 | }) 657 | } 658 | 659 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 660 | let mut result = false; 661 | unsafe { 662 | let status = sys::napi_is_buffer(env, raw, &mut result); 663 | check_status(status)?; 664 | } 665 | Ok(result) 666 | } 667 | } 668 | 669 | impl ValueType for ArrayBuffer { 670 | fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result { 671 | let mut data = ptr::null_mut(); 672 | let mut size: u64 = 0; 673 | let status = unsafe { sys::napi_get_arraybuffer_info(env, raw, &mut data, &mut size) }; 674 | check_status(status)?; 675 | Ok(ArrayBuffer { 676 | data: data as *const u8, 677 | size, 678 | }) 679 | } 680 | 681 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 682 | let mut result = false; 683 | unsafe { 684 | let status = sys::napi_is_arraybuffer(env, raw, &mut result); 685 | check_status(status)?; 686 | } 687 | Ok(result) 688 | } 689 | } 690 | 691 | impl Value { 692 | #[inline] 693 | pub fn from_value(env: &Env, value: &Value) -> Result> { 694 | Ok(Value { 695 | env: env.0, 696 | raw_value: value.raw_value, 697 | value: Buffer::from_raw(env.0, value.into_raw())?, 698 | }) 699 | } 700 | } 701 | 702 | impl ValueType for Function { 703 | fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result { 704 | Ok(Function {}) 705 | } 706 | 707 | fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result { 708 | Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_function) 709 | } 710 | } 711 | 712 | impl Value { 713 | pub fn from_raw_value(env: &Env, raw_value: sys::napi_value, value: T) -> Self { 714 | Self { 715 | env: env.0, 716 | raw_value, 717 | value, 718 | } 719 | } 720 | 721 | pub fn from_raw(env: sys::napi_env, raw_value: sys::napi_value) -> Result { 722 | Ok(Self { 723 | env, 724 | raw_value, 725 | value: T::from_raw(env, raw_value)?, 726 | }) 727 | } 728 | 729 | pub fn into_raw(self) -> sys::napi_value { 730 | self.raw_value 731 | } 732 | 733 | pub fn coerce_to_number(self) -> Result> { 734 | let mut new_raw_value = ptr::null_mut(); 735 | let status = 736 | unsafe { sys::napi_coerce_to_number(self.env, self.raw_value, &mut new_raw_value) }; 737 | check_status(status)?; 738 | Ok(Value { 739 | env: self.env, 740 | raw_value: self.raw_value, 741 | value: Number::from_raw(self.env, self.raw_value)?, 742 | }) 743 | } 744 | 745 | pub fn coerce_to_string(self) -> Result> { 746 | let mut new_raw_value = ptr::null_mut(); 747 | let status = 748 | unsafe { sys::napi_coerce_to_string(self.env, self.raw_value, &mut new_raw_value) }; 749 | check_status(status)?; 750 | Ok(Value { 751 | env: self.env, 752 | raw_value: self.raw_value, 753 | value: JsString, 754 | }) 755 | } 756 | 757 | pub fn coerce_to_object(self) -> Result> { 758 | let mut new_raw_value = ptr::null_mut(); 759 | let status = unsafe { 760 | sys::napi_coerce_to_object( 761 | self.env, 762 | self.raw_value, 763 | (&mut new_raw_value) as *mut sys::napi_value, 764 | ) 765 | }; 766 | check_status(status)?; 767 | Ok(Value { 768 | env: self.env, 769 | raw_value: self.raw_value, 770 | value: Object, 771 | }) 772 | } 773 | 774 | #[inline] 775 | pub fn into_any(self) -> Value { 776 | Value { 777 | env: self.env, 778 | raw_value: self.raw_value, 779 | value: Any, 780 | } 781 | } 782 | } 783 | 784 | #[inline] 785 | fn get_raw_type(env: sys::napi_env, raw_value: sys::napi_value) -> Result { 786 | unsafe { 787 | let value_type = ptr::null_mut(); 788 | check_status(sys::napi_typeof(env, raw_value, value_type))?; 789 | Ok(*value_type) 790 | } 791 | } 792 | 793 | impl Value { 794 | pub fn get_value(&self) -> bool { 795 | self.value.value 796 | } 797 | } 798 | 799 | impl Value { 800 | pub fn len(&self) -> Result { 801 | let mut raw_length = ptr::null_mut(); 802 | unsafe { 803 | let status = sys::napi_get_named_property( 804 | self.env, 805 | self.raw_value, 806 | "length\0".as_ptr() as *const c_char, 807 | &mut raw_length, 808 | ); 809 | check_status(status)?; 810 | } 811 | let length: Value = Value::from_raw(self.env, raw_length)?; 812 | length.try_into() 813 | } 814 | } 815 | 816 | impl Value { 817 | #[inline] 818 | pub fn get_ref(&self) -> Result<&[u8]> { 819 | let mut written_char_count: u64 = 0; 820 | let len = self.len()? + 1; 821 | let mut result = Vec::with_capacity(len); 822 | unsafe { 823 | let status = sys::napi_get_value_string_utf8( 824 | self.env, 825 | self.raw_value, 826 | result.as_mut_ptr(), 827 | len as u64, 828 | &mut written_char_count, 829 | ); 830 | 831 | check_status(status)?; 832 | let ptr = result.as_ptr(); 833 | mem::forget(result); 834 | Ok(slice::from_raw_parts( 835 | ptr as *const u8, 836 | written_char_count as usize, 837 | )) 838 | } 839 | } 840 | 841 | pub fn as_str(&self) -> Result<&str> { 842 | str::from_utf8(self.get_ref()?).map_err(|e| Error { 843 | status: Status::GenericFailure, 844 | reason: Some(format!("{:?}", e)), 845 | }) 846 | } 847 | 848 | pub fn get_ref_mut(&mut self) -> Result<&mut [u8]> { 849 | let mut written_char_count: u64 = 0; 850 | let len = self.len()? + 1; 851 | let mut result = Vec::with_capacity(len); 852 | unsafe { 853 | let status = sys::napi_get_value_string_utf8( 854 | self.env, 855 | self.raw_value, 856 | result.as_mut_ptr(), 857 | len as u64, 858 | &mut written_char_count, 859 | ); 860 | 861 | check_status(status)?; 862 | let ptr = result.as_ptr(); 863 | mem::forget(result); 864 | Ok(slice::from_raw_parts_mut( 865 | ptr as *mut _, 866 | written_char_count as usize, 867 | )) 868 | } 869 | } 870 | } 871 | 872 | impl TryFrom> for Vec { 873 | type Error = Error; 874 | 875 | fn try_from(value: Value) -> Result> { 876 | let mut result = Vec::with_capacity(value.len()? + 1); // Leave room for trailing null byte 877 | 878 | unsafe { 879 | let mut written_char_count = 0; 880 | let status = sys::napi_get_value_string_utf16( 881 | value.env, 882 | value.raw_value, 883 | result.as_mut_ptr(), 884 | result.capacity() as u64, 885 | &mut written_char_count, 886 | ); 887 | check_status(status)?; 888 | result.set_len(written_char_count as usize); 889 | } 890 | 891 | Ok(result) 892 | } 893 | } 894 | 895 | impl TryFrom> for usize { 896 | type Error = Error; 897 | 898 | fn try_from(value: Value) -> Result { 899 | let mut result = 0; 900 | let status = unsafe { sys::napi_get_value_int64(value.env, value.raw_value, &mut result) }; 901 | check_status(status)?; 902 | Ok(result as usize) 903 | } 904 | } 905 | 906 | impl TryFrom> for u32 { 907 | type Error = Error; 908 | 909 | fn try_from(value: Value) -> Result { 910 | let mut result = 0; 911 | let status = unsafe { sys::napi_get_value_uint32(value.env, value.raw_value, &mut result) }; 912 | check_status(status)?; 913 | Ok(result) 914 | } 915 | } 916 | 917 | impl TryFrom> for i32 { 918 | type Error = Error; 919 | 920 | fn try_from(value: Value) -> Result { 921 | let mut result = 0; 922 | let status = unsafe { sys::napi_get_value_int32(value.env, value.raw_value, &mut result) }; 923 | check_status(status)?; 924 | Ok(result) 925 | } 926 | } 927 | 928 | impl TryFrom> for i64 { 929 | type Error = Error; 930 | 931 | fn try_from(value: Value) -> Result { 932 | let mut result = 0; 933 | let status = unsafe { sys::napi_get_value_int64(value.env, value.raw_value, &mut result) }; 934 | check_status(status)?; 935 | Ok(result) 936 | } 937 | } 938 | 939 | impl TryFrom> for f64 { 940 | type Error = Error; 941 | 942 | fn try_from(value: Value) -> Result { 943 | let mut result = 0_f64; 944 | let status = unsafe { sys::napi_get_value_double(value.env, value.raw_value, &mut result) }; 945 | check_status(status)?; 946 | Ok(result) 947 | } 948 | } 949 | 950 | impl Value { 951 | pub fn set_property(&mut self, key: Value, value: Value) -> Result<()> { 952 | let status = unsafe { 953 | sys::napi_set_property( 954 | self.raw_env(), 955 | self.raw_value(), 956 | key.raw_value, 957 | value.raw_value, 958 | ) 959 | }; 960 | check_status(status)?; 961 | Ok(()) 962 | } 963 | 964 | pub fn set_named_property>>(&mut self, name: &str, value: V) -> Result<()> { 965 | let key = CString::new(name)?; 966 | let status = unsafe { 967 | sys::napi_set_named_property( 968 | self.raw_env(), 969 | self.raw_value(), 970 | key.as_ptr(), 971 | value.into().raw_value, 972 | ) 973 | }; 974 | check_status(status)?; 975 | Ok(()) 976 | } 977 | 978 | pub fn get_named_property(&self, name: &str) -> Result> { 979 | let key = CString::new(name)?; 980 | let mut raw_value = ptr::null_mut(); 981 | let status = unsafe { 982 | sys::napi_get_named_property( 983 | self.raw_env(), 984 | self.raw_value(), 985 | key.as_ptr(), 986 | &mut raw_value, 987 | ) 988 | }; 989 | check_status(status)?; 990 | Value::::from_raw(self.env, raw_value) 991 | } 992 | 993 | pub fn get_property_names(&self) -> Result> { 994 | let mut raw_value = ptr::null_mut(); 995 | let status = 996 | unsafe { sys::napi_get_property_names(self.raw_env(), self.raw_value(), &mut raw_value) }; 997 | check_status(status)?; 998 | Value::::from_raw(self.env, raw_value) 999 | } 1000 | 1001 | pub fn set_index<'a, T>(&mut self, index: usize, value: Value) -> Result<()> { 1002 | self.set_property(Env::from_raw(self.env).create_int64(index as i64)?, value) 1003 | } 1004 | 1005 | pub fn get_index(&self, index: u32) -> Result> { 1006 | let mut raw_value = ptr::null_mut(); 1007 | let status = 1008 | unsafe { sys::napi_get_element(self.raw_env(), self.raw_value(), index, &mut raw_value) }; 1009 | check_status(status)?; 1010 | Value::::from_raw(self.env, raw_value) 1011 | } 1012 | 1013 | pub fn is_array(&self) -> Result { 1014 | let mut is_array = false; 1015 | let status = unsafe { sys::napi_is_array(self.raw_env(), self.raw_value(), &mut is_array) }; 1016 | check_status(status)?; 1017 | Ok(is_array) 1018 | } 1019 | 1020 | pub fn is_buffer(&self) -> Result { 1021 | let mut is_buffer = false; 1022 | let status = unsafe { sys::napi_is_buffer(self.raw_env(), self.raw_value(), &mut is_buffer) }; 1023 | check_status(status)?; 1024 | Ok(is_buffer) 1025 | } 1026 | 1027 | pub fn to_buffer(&self) -> Result> { 1028 | Value::from_raw(self.env, self.raw_value) 1029 | } 1030 | 1031 | pub fn get_array_length(&self) -> Result { 1032 | if self.is_array()? != true { 1033 | return Err(Error { 1034 | status: Status::ArrayExpected, 1035 | reason: Some("Object is not array".to_owned()), 1036 | }); 1037 | } 1038 | let mut length: u32 = 0; 1039 | let status = 1040 | unsafe { sys::napi_get_array_length(self.raw_env(), self.raw_value(), &mut length) }; 1041 | check_status(status)?; 1042 | Ok(length) 1043 | } 1044 | 1045 | fn raw_value(&self) -> sys::napi_value { 1046 | self.raw_value 1047 | } 1048 | 1049 | fn raw_env(&self) -> sys::napi_env { 1050 | self.env 1051 | } 1052 | } 1053 | 1054 | impl AsRef<[u8]> for Value { 1055 | fn as_ref(&self) -> &[u8] { 1056 | self.deref() 1057 | } 1058 | } 1059 | 1060 | impl Deref for Value { 1061 | type Target = [u8]; 1062 | 1063 | fn deref(&self) -> &[u8] { 1064 | unsafe { slice::from_raw_parts(self.value.data, self.value.size as usize) } 1065 | } 1066 | } 1067 | 1068 | impl DerefMut for Value { 1069 | fn deref_mut(&mut self) -> &mut [u8] { 1070 | unsafe { slice::from_raw_parts_mut(self.value.data as *mut _, self.value.size as usize) } 1071 | } 1072 | } 1073 | 1074 | impl Deref for Value { 1075 | type Target = [u8]; 1076 | 1077 | fn deref(&self) -> &[u8] { 1078 | unsafe { slice::from_raw_parts(self.value.data, self.value.size as usize) } 1079 | } 1080 | } 1081 | 1082 | impl DerefMut for Value { 1083 | fn deref_mut(&mut self) -> &mut [u8] { 1084 | unsafe { slice::from_raw_parts_mut(self.value.data as *mut _, self.value.size as usize) } 1085 | } 1086 | } 1087 | 1088 | impl Value { 1089 | pub fn call(&self, this: Option<&Value>, args: &[Value]) -> Result> { 1090 | let raw_this = this 1091 | .map(|v| v.into_raw()) 1092 | .or_else(|| { 1093 | Env::from_raw(self.env) 1094 | .get_undefined() 1095 | .ok() 1096 | .map(|u| u.into_raw()) 1097 | }) 1098 | .ok_or(Error { 1099 | status: Status::Unknown, 1100 | reason: Some("Get raw this failed".to_owned()), 1101 | })?; 1102 | let mut raw_args = unsafe { mem::MaybeUninit::<[sys::napi_value; 8]>::uninit().assume_init() }; 1103 | for (i, arg) in args.into_iter().enumerate() { 1104 | raw_args[i] = arg.raw_value; 1105 | } 1106 | let mut return_value = ptr::null_mut(); 1107 | let status = unsafe { 1108 | sys::napi_call_function( 1109 | self.env, 1110 | raw_this, 1111 | self.raw_value, 1112 | args.len() as u64, 1113 | &raw_args[0], 1114 | &mut return_value, 1115 | ) 1116 | }; 1117 | check_status(status)?; 1118 | 1119 | Value::from_raw(self.env, return_value) 1120 | } 1121 | } 1122 | 1123 | impl Value { 1124 | pub fn get_type(&self) -> Result { 1125 | get_raw_type(self.env, self.raw_value) 1126 | } 1127 | } 1128 | 1129 | impl Drop for Ref { 1130 | fn drop(&mut self) { 1131 | unsafe { 1132 | let mut ref_count = 0; 1133 | let status = sys::napi_reference_unref(self.raw_env, self.raw_ref, &mut ref_count); 1134 | debug_assert!(Status::from(status) == Status::Ok); 1135 | 1136 | if ref_count == 0 { 1137 | let status = sys::napi_delete_reference(self.raw_env, self.raw_ref); 1138 | debug_assert!(Status::from(status) == Status::Ok); 1139 | } 1140 | } 1141 | } 1142 | } 1143 | 1144 | impl Property { 1145 | pub fn new(name: &str) -> Self { 1146 | Property { 1147 | name: RustString::from(name), 1148 | raw_descriptor: sys::napi_property_descriptor { 1149 | utf8name: ptr::null_mut(), 1150 | name: ptr::null_mut(), 1151 | method: None, 1152 | getter: None, 1153 | setter: None, 1154 | value: ptr::null_mut(), 1155 | attributes: sys::napi_property_attributes::napi_default, 1156 | data: ptr::null_mut(), 1157 | }, 1158 | } 1159 | } 1160 | 1161 | pub fn with_value(mut self, value: Value) -> Self { 1162 | self.raw_descriptor.value = value.raw_value; 1163 | self 1164 | } 1165 | 1166 | pub fn with_method(mut self, callback: Callback) -> Self { 1167 | self.raw_descriptor.method = Some(callback); 1168 | self 1169 | } 1170 | 1171 | pub fn with_getter(mut self, callback: Callback) -> Self { 1172 | self.raw_descriptor.getter = Some(callback); 1173 | self 1174 | } 1175 | 1176 | fn into_raw(mut self, env: &Env) -> Result { 1177 | self.raw_descriptor.name = env.create_string(&self.name)?.into_raw(); 1178 | Ok(self.raw_descriptor) 1179 | } 1180 | } 1181 | 1182 | impl TaggedObject { 1183 | fn new(object: T) -> Self { 1184 | TaggedObject { 1185 | type_id: TypeId::of::(), 1186 | object: Some(object), 1187 | } 1188 | } 1189 | } 1190 | 1191 | #[inline] 1192 | fn check_status(code: sys::napi_status) -> Result<()> { 1193 | let status = Status::from(code); 1194 | match status { 1195 | Status::Ok => Ok(()), 1196 | _ => Err(Error::from_status(status)), 1197 | } 1198 | } 1199 | 1200 | unsafe extern "C" fn raw_finalize( 1201 | _raw_env: sys::napi_env, 1202 | finalize_data: *mut c_void, 1203 | _finalize_hint: *mut c_void, 1204 | ) { 1205 | let tagged_object: *mut TaggedObject = mem::transmute(finalize_data); 1206 | Box::from_raw(tagged_object); 1207 | } 1208 | 1209 | unsafe extern "C" fn drop_buffer(env: sys::napi_env, finalize_data: *mut c_void, len: *mut c_void) { 1210 | let length = Box::from_raw(len as *mut u64); 1211 | let length = length.as_ref(); 1212 | let length = *length as usize; 1213 | let _ = Vec::from_raw_parts(finalize_data as *mut u8, length, length); 1214 | let mut changed = 0; 1215 | let ajust_external_memory_status = 1216 | sys::napi_adjust_external_memory(env, -(length as i64), &mut changed); 1217 | debug_assert!(Status::from(ajust_external_memory_status) == Status::Ok); 1218 | } 1219 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.8.3" 7 | resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" 8 | integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== 9 | dependencies: 10 | "@babel/highlight" "^7.8.3" 11 | 12 | "@babel/helper-validator-identifier@^7.9.0": 13 | version "7.9.5" 14 | resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" 15 | integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== 16 | 17 | "@babel/highlight@^7.8.3": 18 | version "7.9.0" 19 | resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" 20 | integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.9.0" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@babel/runtime@^7.9.2": 27 | version "7.9.6" 28 | resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" 29 | integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== 30 | dependencies: 31 | regenerator-runtime "^0.13.4" 32 | 33 | "@types/color-name@^1.1.1": 34 | version "1.1.1" 35 | resolved "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" 36 | integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== 37 | 38 | "@types/node@^14.0.13": 39 | version "14.0.13" 40 | resolved "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz#ee1128e881b874c371374c1f72201893616417c9" 41 | integrity sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA== 42 | 43 | "@types/parse-json@^4.0.0": 44 | version "4.0.0" 45 | resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" 46 | integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== 47 | 48 | aggregate-error@^3.0.0: 49 | version "3.0.1" 50 | resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" 51 | integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== 52 | dependencies: 53 | clean-stack "^2.0.0" 54 | indent-string "^4.0.0" 55 | 56 | ansi-colors@^3.2.1: 57 | version "3.2.4" 58 | resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" 59 | integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== 60 | 61 | ansi-escapes@^4.3.0: 62 | version "4.3.1" 63 | resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" 64 | integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== 65 | dependencies: 66 | type-fest "^0.11.0" 67 | 68 | ansi-regex@^5.0.0: 69 | version "5.0.0" 70 | resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 71 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 72 | 73 | ansi-styles@^3.2.1: 74 | version "3.2.1" 75 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 76 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 77 | dependencies: 78 | color-convert "^1.9.0" 79 | 80 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 81 | version "4.2.1" 82 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" 83 | integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== 84 | dependencies: 85 | "@types/color-name" "^1.1.1" 86 | color-convert "^2.0.1" 87 | 88 | astral-regex@^2.0.0: 89 | version "2.0.0" 90 | resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" 91 | integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== 92 | 93 | balanced-match@^1.0.0: 94 | version "1.0.0" 95 | resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 96 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 97 | 98 | brace-expansion@^1.1.7: 99 | version "1.1.11" 100 | resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 101 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 102 | dependencies: 103 | balanced-match "^1.0.0" 104 | concat-map "0.0.1" 105 | 106 | braces@^3.0.1: 107 | version "3.0.2" 108 | resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 109 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 110 | dependencies: 111 | fill-range "^7.0.1" 112 | 113 | callsites@^3.0.0: 114 | version "3.1.0" 115 | resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 116 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 117 | 118 | chalk@^2.0.0, chalk@^2.4.1: 119 | version "2.4.2" 120 | resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 121 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 122 | dependencies: 123 | ansi-styles "^3.2.1" 124 | escape-string-regexp "^1.0.5" 125 | supports-color "^5.3.0" 126 | 127 | chalk@^4.0.0: 128 | version "4.0.0" 129 | resolved "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" 130 | integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== 131 | dependencies: 132 | ansi-styles "^4.1.0" 133 | supports-color "^7.1.0" 134 | 135 | ci-info@^2.0.0: 136 | version "2.0.0" 137 | resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" 138 | integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== 139 | 140 | clean-stack@^2.0.0: 141 | version "2.2.0" 142 | resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" 143 | integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== 144 | 145 | cli-cursor@^3.1.0: 146 | version "3.1.0" 147 | resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" 148 | integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== 149 | dependencies: 150 | restore-cursor "^3.1.0" 151 | 152 | cli-truncate@2.1.0, cli-truncate@^2.1.0: 153 | version "2.1.0" 154 | resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" 155 | integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== 156 | dependencies: 157 | slice-ansi "^3.0.0" 158 | string-width "^4.2.0" 159 | 160 | color-convert@^1.9.0: 161 | version "1.9.3" 162 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 163 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 164 | dependencies: 165 | color-name "1.1.3" 166 | 167 | color-convert@^2.0.1: 168 | version "2.0.1" 169 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 170 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 171 | dependencies: 172 | color-name "~1.1.4" 173 | 174 | color-name@1.1.3: 175 | version "1.1.3" 176 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 177 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 178 | 179 | color-name@~1.1.4: 180 | version "1.1.4" 181 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 182 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 183 | 184 | commander@^5.1.0: 185 | version "5.1.0" 186 | resolved "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" 187 | integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== 188 | 189 | compare-versions@^3.6.0: 190 | version "3.6.0" 191 | resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" 192 | integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== 193 | 194 | concat-map@0.0.1: 195 | version "0.0.1" 196 | resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 197 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 198 | 199 | cosmiconfig@^6.0.0: 200 | version "6.0.0" 201 | resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" 202 | integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== 203 | dependencies: 204 | "@types/parse-json" "^4.0.0" 205 | import-fresh "^3.1.0" 206 | parse-json "^5.0.0" 207 | path-type "^4.0.0" 208 | yaml "^1.7.2" 209 | 210 | cross-spawn@^6.0.5: 211 | version "6.0.5" 212 | resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 213 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 214 | dependencies: 215 | nice-try "^1.0.4" 216 | path-key "^2.0.1" 217 | semver "^5.5.0" 218 | shebang-command "^1.2.0" 219 | which "^1.2.9" 220 | 221 | cross-spawn@^7.0.0: 222 | version "7.0.2" 223 | resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz#d0d7dcfa74e89115c7619f4f721a94e1fdb716d6" 224 | integrity sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw== 225 | dependencies: 226 | path-key "^3.1.0" 227 | shebang-command "^2.0.0" 228 | which "^2.0.1" 229 | 230 | debug@^4.1.1: 231 | version "4.1.1" 232 | resolved "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" 233 | integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== 234 | dependencies: 235 | ms "^2.1.1" 236 | 237 | dedent@^0.7.0: 238 | version "0.7.0" 239 | resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" 240 | integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= 241 | 242 | define-properties@^1.1.2, define-properties@^1.1.3: 243 | version "1.1.3" 244 | resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" 245 | integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== 246 | dependencies: 247 | object-keys "^1.0.12" 248 | 249 | emoji-regex@^8.0.0: 250 | version "8.0.0" 251 | resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 252 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 253 | 254 | end-of-stream@^1.1.0: 255 | version "1.4.4" 256 | resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 257 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 258 | dependencies: 259 | once "^1.4.0" 260 | 261 | enquirer@^2.3.5: 262 | version "2.3.5" 263 | resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz#3ab2b838df0a9d8ab9e7dff235b0e8712ef92381" 264 | integrity sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA== 265 | dependencies: 266 | ansi-colors "^3.2.1" 267 | 268 | error-ex@^1.3.1: 269 | version "1.3.2" 270 | resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 271 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 272 | dependencies: 273 | is-arrayish "^0.2.1" 274 | 275 | es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: 276 | version "1.17.5" 277 | resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" 278 | integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== 279 | dependencies: 280 | es-to-primitive "^1.2.1" 281 | function-bind "^1.1.1" 282 | has "^1.0.3" 283 | has-symbols "^1.0.1" 284 | is-callable "^1.1.5" 285 | is-regex "^1.0.5" 286 | object-inspect "^1.7.0" 287 | object-keys "^1.1.1" 288 | object.assign "^4.1.0" 289 | string.prototype.trimleft "^2.1.1" 290 | string.prototype.trimright "^2.1.1" 291 | 292 | es-to-primitive@^1.2.1: 293 | version "1.2.1" 294 | resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" 295 | integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== 296 | dependencies: 297 | is-callable "^1.1.4" 298 | is-date-object "^1.0.1" 299 | is-symbol "^1.0.2" 300 | 301 | escape-string-regexp@^1.0.5: 302 | version "1.0.5" 303 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 304 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 305 | 306 | execa@^4.0.1: 307 | version "4.0.1" 308 | resolved "https://registry.npmjs.org/execa/-/execa-4.0.1.tgz#988488781f1f0238cd156f7aaede11c3e853b4c1" 309 | integrity sha512-SCjM/zlBdOK8Q5TIjOn6iEHZaPHFsMoTxXQ2nvUvtPnuohz3H2dIozSg+etNR98dGoYUp2ENSKLL/XaMmbxVgw== 310 | dependencies: 311 | cross-spawn "^7.0.0" 312 | get-stream "^5.0.0" 313 | human-signals "^1.1.1" 314 | is-stream "^2.0.0" 315 | merge-stream "^2.0.0" 316 | npm-run-path "^4.0.0" 317 | onetime "^5.1.0" 318 | signal-exit "^3.0.2" 319 | strip-final-newline "^2.0.0" 320 | 321 | figures@^3.2.0: 322 | version "3.2.0" 323 | resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" 324 | integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== 325 | dependencies: 326 | escape-string-regexp "^1.0.5" 327 | 328 | fill-range@^7.0.1: 329 | version "7.0.1" 330 | resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 331 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 332 | dependencies: 333 | to-regex-range "^5.0.1" 334 | 335 | find-up@^4.0.0: 336 | version "4.1.0" 337 | resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 338 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 339 | dependencies: 340 | locate-path "^5.0.0" 341 | path-exists "^4.0.0" 342 | 343 | find-versions@^3.2.0: 344 | version "3.2.0" 345 | resolved "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" 346 | integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== 347 | dependencies: 348 | semver-regex "^2.0.0" 349 | 350 | function-bind@^1.1.1: 351 | version "1.1.1" 352 | resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 353 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 354 | 355 | get-own-enumerable-property-symbols@^3.0.0: 356 | version "3.0.2" 357 | resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" 358 | integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== 359 | 360 | get-stream@^5.0.0: 361 | version "5.1.0" 362 | resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" 363 | integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== 364 | dependencies: 365 | pump "^3.0.0" 366 | 367 | graceful-fs@^4.1.2: 368 | version "4.2.4" 369 | resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" 370 | integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== 371 | 372 | has-flag@^3.0.0: 373 | version "3.0.0" 374 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 375 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 376 | 377 | has-flag@^4.0.0: 378 | version "4.0.0" 379 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 380 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 381 | 382 | has-symbols@^1.0.0, has-symbols@^1.0.1: 383 | version "1.0.1" 384 | resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" 385 | integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== 386 | 387 | has@^1.0.3: 388 | version "1.0.3" 389 | resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 390 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 391 | dependencies: 392 | function-bind "^1.1.1" 393 | 394 | hosted-git-info@^2.1.4: 395 | version "2.8.8" 396 | resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" 397 | integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== 398 | 399 | human-signals@^1.1.1: 400 | version "1.1.1" 401 | resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" 402 | integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== 403 | 404 | husky@^4.2.5: 405 | version "4.2.5" 406 | resolved "https://registry.npmjs.org/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36" 407 | integrity sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ== 408 | dependencies: 409 | chalk "^4.0.0" 410 | ci-info "^2.0.0" 411 | compare-versions "^3.6.0" 412 | cosmiconfig "^6.0.0" 413 | find-versions "^3.2.0" 414 | opencollective-postinstall "^2.0.2" 415 | pkg-dir "^4.2.0" 416 | please-upgrade-node "^3.2.0" 417 | slash "^3.0.0" 418 | which-pm-runs "^1.0.0" 419 | 420 | import-fresh@^3.1.0: 421 | version "3.2.1" 422 | resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" 423 | integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== 424 | dependencies: 425 | parent-module "^1.0.0" 426 | resolve-from "^4.0.0" 427 | 428 | indent-string@^4.0.0: 429 | version "4.0.0" 430 | resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" 431 | integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== 432 | 433 | is-arrayish@^0.2.1: 434 | version "0.2.1" 435 | resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 436 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 437 | 438 | is-callable@^1.1.4, is-callable@^1.1.5: 439 | version "1.1.5" 440 | resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" 441 | integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== 442 | 443 | is-date-object@^1.0.1: 444 | version "1.0.2" 445 | resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" 446 | integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== 447 | 448 | is-fullwidth-code-point@^3.0.0: 449 | version "3.0.0" 450 | resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 451 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 452 | 453 | is-number@^7.0.0: 454 | version "7.0.0" 455 | resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 456 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 457 | 458 | is-obj@^1.0.1: 459 | version "1.0.1" 460 | resolved "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" 461 | integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= 462 | 463 | is-regex@^1.0.5: 464 | version "1.0.5" 465 | resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" 466 | integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== 467 | dependencies: 468 | has "^1.0.3" 469 | 470 | is-regexp@^1.0.0: 471 | version "1.0.0" 472 | resolved "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" 473 | integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= 474 | 475 | is-stream@^2.0.0: 476 | version "2.0.0" 477 | resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" 478 | integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== 479 | 480 | is-symbol@^1.0.2: 481 | version "1.0.3" 482 | resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" 483 | integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== 484 | dependencies: 485 | has-symbols "^1.0.1" 486 | 487 | isexe@^2.0.0: 488 | version "2.0.0" 489 | resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 490 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 491 | 492 | js-tokens@^4.0.0: 493 | version "4.0.0" 494 | resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 495 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 496 | 497 | json-parse-better-errors@^1.0.1: 498 | version "1.0.2" 499 | resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 500 | integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 501 | 502 | lines-and-columns@^1.1.6: 503 | version "1.1.6" 504 | resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" 505 | integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= 506 | 507 | lint-staged@^10.2.10: 508 | version "10.2.10" 509 | resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-10.2.10.tgz#f0f78bf8786bbe90e1775a0dc540f7f12b6a79b2" 510 | integrity sha512-dgelFaNH6puUGAcU+OVMgbfpKSerNYsPSn6+nlbRDjovL0KigpsVpCu0PFZG6BJxX8gnHJqaZlR9krZamQsb0w== 511 | dependencies: 512 | chalk "^4.0.0" 513 | cli-truncate "2.1.0" 514 | commander "^5.1.0" 515 | cosmiconfig "^6.0.0" 516 | debug "^4.1.1" 517 | dedent "^0.7.0" 518 | enquirer "^2.3.5" 519 | execa "^4.0.1" 520 | listr2 "^2.1.0" 521 | log-symbols "^4.0.0" 522 | micromatch "^4.0.2" 523 | normalize-path "^3.0.0" 524 | please-upgrade-node "^3.2.0" 525 | string-argv "0.3.1" 526 | stringify-object "^3.3.0" 527 | 528 | listr2@^2.1.0: 529 | version "2.1.3" 530 | resolved "https://registry.npmjs.org/listr2/-/listr2-2.1.3.tgz#f527e197de12ad8c488c566921fa2da34cbc67f6" 531 | integrity sha512-6oy3QhrZAlJGrG8oPcRp1hix1zUpb5AvyvZ5je979HCyf48tIj3Hn1TG5+rfyhz30t7HfySH/OIaVbwrI2kruA== 532 | dependencies: 533 | chalk "^4.0.0" 534 | cli-truncate "^2.1.0" 535 | figures "^3.2.0" 536 | indent-string "^4.0.0" 537 | log-update "^4.0.0" 538 | p-map "^4.0.0" 539 | rxjs "^6.5.5" 540 | through "^2.3.8" 541 | 542 | load-json-file@^4.0.0: 543 | version "4.0.0" 544 | resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" 545 | integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= 546 | dependencies: 547 | graceful-fs "^4.1.2" 548 | parse-json "^4.0.0" 549 | pify "^3.0.0" 550 | strip-bom "^3.0.0" 551 | 552 | locate-path@^5.0.0: 553 | version "5.0.0" 554 | resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 555 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 556 | dependencies: 557 | p-locate "^4.1.0" 558 | 559 | log-symbols@^4.0.0: 560 | version "4.0.0" 561 | resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" 562 | integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== 563 | dependencies: 564 | chalk "^4.0.0" 565 | 566 | log-update@^4.0.0: 567 | version "4.0.0" 568 | resolved "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" 569 | integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== 570 | dependencies: 571 | ansi-escapes "^4.3.0" 572 | cli-cursor "^3.1.0" 573 | slice-ansi "^4.0.0" 574 | wrap-ansi "^6.2.0" 575 | 576 | memorystream@^0.3.1: 577 | version "0.3.1" 578 | resolved "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" 579 | integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= 580 | 581 | merge-stream@^2.0.0: 582 | version "2.0.0" 583 | resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 584 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 585 | 586 | micromatch@^4.0.2: 587 | version "4.0.2" 588 | resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" 589 | integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== 590 | dependencies: 591 | braces "^3.0.1" 592 | picomatch "^2.0.5" 593 | 594 | mimic-fn@^2.1.0: 595 | version "2.1.0" 596 | resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" 597 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 598 | 599 | minimatch@^3.0.4: 600 | version "3.0.4" 601 | resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 602 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 603 | dependencies: 604 | brace-expansion "^1.1.7" 605 | 606 | minimist@^1.2.5: 607 | version "1.2.5" 608 | resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 609 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 610 | 611 | ms@^2.1.1: 612 | version "2.1.2" 613 | resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 614 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 615 | 616 | nice-try@^1.0.4: 617 | version "1.0.5" 618 | resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 619 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== 620 | 621 | normalize-package-data@^2.3.2: 622 | version "2.5.0" 623 | resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 624 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 625 | dependencies: 626 | hosted-git-info "^2.1.4" 627 | resolve "^1.10.0" 628 | semver "2 || 3 || 4 || 5" 629 | validate-npm-package-license "^3.0.1" 630 | 631 | normalize-path@^3.0.0: 632 | version "3.0.0" 633 | resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 634 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 635 | 636 | npm-run-all@^4.1.5: 637 | version "4.1.5" 638 | resolved "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" 639 | integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== 640 | dependencies: 641 | ansi-styles "^3.2.1" 642 | chalk "^2.4.1" 643 | cross-spawn "^6.0.5" 644 | memorystream "^0.3.1" 645 | minimatch "^3.0.4" 646 | pidtree "^0.3.0" 647 | read-pkg "^3.0.0" 648 | shell-quote "^1.6.1" 649 | string.prototype.padend "^3.0.0" 650 | 651 | npm-run-path@^4.0.0: 652 | version "4.0.1" 653 | resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" 654 | integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== 655 | dependencies: 656 | path-key "^3.0.0" 657 | 658 | object-inspect@^1.7.0: 659 | version "1.7.0" 660 | resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" 661 | integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== 662 | 663 | object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: 664 | version "1.1.1" 665 | resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 666 | integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 667 | 668 | object.assign@^4.1.0: 669 | version "4.1.0" 670 | resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" 671 | integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== 672 | dependencies: 673 | define-properties "^1.1.2" 674 | function-bind "^1.1.1" 675 | has-symbols "^1.0.0" 676 | object-keys "^1.0.11" 677 | 678 | once@^1.3.1, once@^1.4.0: 679 | version "1.4.0" 680 | resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 681 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 682 | dependencies: 683 | wrappy "1" 684 | 685 | onetime@^5.1.0: 686 | version "5.1.0" 687 | resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" 688 | integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== 689 | dependencies: 690 | mimic-fn "^2.1.0" 691 | 692 | opencollective-postinstall@^2.0.2: 693 | version "2.0.2" 694 | resolved "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" 695 | integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== 696 | 697 | p-limit@^2.2.0: 698 | version "2.3.0" 699 | resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 700 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 701 | dependencies: 702 | p-try "^2.0.0" 703 | 704 | p-locate@^4.1.0: 705 | version "4.1.0" 706 | resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 707 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 708 | dependencies: 709 | p-limit "^2.2.0" 710 | 711 | p-map@^4.0.0: 712 | version "4.0.0" 713 | resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" 714 | integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== 715 | dependencies: 716 | aggregate-error "^3.0.0" 717 | 718 | p-try@^2.0.0: 719 | version "2.2.0" 720 | resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 721 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 722 | 723 | parent-module@^1.0.0: 724 | version "1.0.1" 725 | resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 726 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 727 | dependencies: 728 | callsites "^3.0.0" 729 | 730 | parse-json@^4.0.0: 731 | version "4.0.0" 732 | resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 733 | integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= 734 | dependencies: 735 | error-ex "^1.3.1" 736 | json-parse-better-errors "^1.0.1" 737 | 738 | parse-json@^5.0.0: 739 | version "5.0.0" 740 | resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" 741 | integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== 742 | dependencies: 743 | "@babel/code-frame" "^7.0.0" 744 | error-ex "^1.3.1" 745 | json-parse-better-errors "^1.0.1" 746 | lines-and-columns "^1.1.6" 747 | 748 | path-exists@^4.0.0: 749 | version "4.0.0" 750 | resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 751 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 752 | 753 | path-key@^2.0.1: 754 | version "2.0.1" 755 | resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 756 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 757 | 758 | path-key@^3.0.0, path-key@^3.1.0: 759 | version "3.1.1" 760 | resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 761 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 762 | 763 | path-parse@^1.0.6: 764 | version "1.0.6" 765 | resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 766 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 767 | 768 | path-type@^3.0.0: 769 | version "3.0.0" 770 | resolved "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" 771 | integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== 772 | dependencies: 773 | pify "^3.0.0" 774 | 775 | path-type@^4.0.0: 776 | version "4.0.0" 777 | resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" 778 | integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 779 | 780 | picomatch@^2.0.5: 781 | version "2.2.2" 782 | resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" 783 | integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== 784 | 785 | pidtree@^0.3.0: 786 | version "0.3.1" 787 | resolved "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" 788 | integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== 789 | 790 | pify@^3.0.0: 791 | version "3.0.0" 792 | resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" 793 | integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= 794 | 795 | pkg-dir@^4.2.0: 796 | version "4.2.0" 797 | resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 798 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 799 | dependencies: 800 | find-up "^4.0.0" 801 | 802 | please-upgrade-node@^3.2.0: 803 | version "3.2.0" 804 | resolved "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" 805 | integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== 806 | dependencies: 807 | semver-compare "^1.0.0" 808 | 809 | prettier@^2.0.5: 810 | version "2.0.5" 811 | resolved "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" 812 | integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== 813 | 814 | pump@^3.0.0: 815 | version "3.0.0" 816 | resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 817 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 818 | dependencies: 819 | end-of-stream "^1.1.0" 820 | once "^1.3.1" 821 | 822 | read-pkg@^3.0.0: 823 | version "3.0.0" 824 | resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" 825 | integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= 826 | dependencies: 827 | load-json-file "^4.0.0" 828 | normalize-package-data "^2.3.2" 829 | path-type "^3.0.0" 830 | 831 | regenerator-runtime@^0.13.4: 832 | version "0.13.5" 833 | resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" 834 | integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== 835 | 836 | resolve-from@^4.0.0: 837 | version "4.0.0" 838 | resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 839 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 840 | 841 | resolve@^1.10.0: 842 | version "1.17.0" 843 | resolved "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" 844 | integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== 845 | dependencies: 846 | path-parse "^1.0.6" 847 | 848 | restore-cursor@^3.1.0: 849 | version "3.1.0" 850 | resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" 851 | integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== 852 | dependencies: 853 | onetime "^5.1.0" 854 | signal-exit "^3.0.2" 855 | 856 | rxjs@^6.5.5: 857 | version "6.5.5" 858 | resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" 859 | integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== 860 | dependencies: 861 | tslib "^1.9.0" 862 | 863 | semver-compare@^1.0.0: 864 | version "1.0.0" 865 | resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" 866 | integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= 867 | 868 | semver-regex@^2.0.0: 869 | version "2.0.0" 870 | resolved "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" 871 | integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== 872 | 873 | "semver@2 || 3 || 4 || 5", semver@^5.5.0: 874 | version "5.7.1" 875 | resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 876 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 877 | 878 | shebang-command@^1.2.0: 879 | version "1.2.0" 880 | resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 881 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 882 | dependencies: 883 | shebang-regex "^1.0.0" 884 | 885 | shebang-command@^2.0.0: 886 | version "2.0.0" 887 | resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 888 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 889 | dependencies: 890 | shebang-regex "^3.0.0" 891 | 892 | shebang-regex@^1.0.0: 893 | version "1.0.0" 894 | resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 895 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 896 | 897 | shebang-regex@^3.0.0: 898 | version "3.0.0" 899 | resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 900 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 901 | 902 | shell-quote@^1.6.1: 903 | version "1.7.2" 904 | resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" 905 | integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== 906 | 907 | signal-exit@^3.0.2: 908 | version "3.0.3" 909 | resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 910 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== 911 | 912 | slash@^3.0.0: 913 | version "3.0.0" 914 | resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" 915 | integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== 916 | 917 | slice-ansi@^3.0.0: 918 | version "3.0.0" 919 | resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" 920 | integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== 921 | dependencies: 922 | ansi-styles "^4.0.0" 923 | astral-regex "^2.0.0" 924 | is-fullwidth-code-point "^3.0.0" 925 | 926 | slice-ansi@^4.0.0: 927 | version "4.0.0" 928 | resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" 929 | integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== 930 | dependencies: 931 | ansi-styles "^4.0.0" 932 | astral-regex "^2.0.0" 933 | is-fullwidth-code-point "^3.0.0" 934 | 935 | spdx-correct@^3.0.0: 936 | version "3.1.0" 937 | resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" 938 | integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== 939 | dependencies: 940 | spdx-expression-parse "^3.0.0" 941 | spdx-license-ids "^3.0.0" 942 | 943 | spdx-exceptions@^2.1.0: 944 | version "2.3.0" 945 | resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" 946 | integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== 947 | 948 | spdx-expression-parse@^3.0.0: 949 | version "3.0.0" 950 | resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 951 | integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== 952 | dependencies: 953 | spdx-exceptions "^2.1.0" 954 | spdx-license-ids "^3.0.0" 955 | 956 | spdx-license-ids@^3.0.0: 957 | version "3.0.5" 958 | resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" 959 | integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== 960 | 961 | string-argv@0.3.1: 962 | version "0.3.1" 963 | resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" 964 | integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== 965 | 966 | string-width@^4.1.0, string-width@^4.2.0: 967 | version "4.2.0" 968 | resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" 969 | integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== 970 | dependencies: 971 | emoji-regex "^8.0.0" 972 | is-fullwidth-code-point "^3.0.0" 973 | strip-ansi "^6.0.0" 974 | 975 | string.prototype.padend@^3.0.0: 976 | version "3.1.0" 977 | resolved "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz#dc08f57a8010dc5c153550318f67e13adbb72ac3" 978 | integrity sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA== 979 | dependencies: 980 | define-properties "^1.1.3" 981 | es-abstract "^1.17.0-next.1" 982 | 983 | string.prototype.trimend@^1.0.0: 984 | version "1.0.1" 985 | resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" 986 | integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== 987 | dependencies: 988 | define-properties "^1.1.3" 989 | es-abstract "^1.17.5" 990 | 991 | string.prototype.trimleft@^2.1.1: 992 | version "2.1.2" 993 | resolved "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" 994 | integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== 995 | dependencies: 996 | define-properties "^1.1.3" 997 | es-abstract "^1.17.5" 998 | string.prototype.trimstart "^1.0.0" 999 | 1000 | string.prototype.trimright@^2.1.1: 1001 | version "2.1.2" 1002 | resolved "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" 1003 | integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== 1004 | dependencies: 1005 | define-properties "^1.1.3" 1006 | es-abstract "^1.17.5" 1007 | string.prototype.trimend "^1.0.0" 1008 | 1009 | string.prototype.trimstart@^1.0.0: 1010 | version "1.0.1" 1011 | resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" 1012 | integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== 1013 | dependencies: 1014 | define-properties "^1.1.3" 1015 | es-abstract "^1.17.5" 1016 | 1017 | stringify-object@^3.3.0: 1018 | version "3.3.0" 1019 | resolved "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" 1020 | integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== 1021 | dependencies: 1022 | get-own-enumerable-property-symbols "^3.0.0" 1023 | is-obj "^1.0.1" 1024 | is-regexp "^1.0.0" 1025 | 1026 | strip-ansi@^6.0.0: 1027 | version "6.0.0" 1028 | resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" 1029 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== 1030 | dependencies: 1031 | ansi-regex "^5.0.0" 1032 | 1033 | strip-bom@^3.0.0: 1034 | version "3.0.0" 1035 | resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 1036 | integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= 1037 | 1038 | strip-final-newline@^2.0.0: 1039 | version "2.0.0" 1040 | resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" 1041 | integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== 1042 | 1043 | supports-color@^5.3.0: 1044 | version "5.5.0" 1045 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1046 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1047 | dependencies: 1048 | has-flag "^3.0.0" 1049 | 1050 | supports-color@^7.1.0: 1051 | version "7.1.0" 1052 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" 1053 | integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== 1054 | dependencies: 1055 | has-flag "^4.0.0" 1056 | 1057 | through@^2.3.8: 1058 | version "2.3.8" 1059 | resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1060 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 1061 | 1062 | to-regex-range@^5.0.1: 1063 | version "5.0.1" 1064 | resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1065 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1066 | dependencies: 1067 | is-number "^7.0.0" 1068 | 1069 | toml@^3.0.0: 1070 | version "3.0.0" 1071 | resolved "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" 1072 | integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== 1073 | 1074 | tslib@^1.9.0: 1075 | version "1.11.2" 1076 | resolved "https://registry.npmjs.org/tslib/-/tslib-1.11.2.tgz#9c79d83272c9a7aaf166f73915c9667ecdde3cc9" 1077 | integrity sha512-tTSkux6IGPnUGUd1XAZHcpu85MOkIl5zX49pO+jfsie3eP0B6pyhOlLXm3cAC6T7s+euSDDUUV+Acop5WmtkVg== 1078 | 1079 | type-fest@^0.11.0: 1080 | version "0.11.0" 1081 | resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" 1082 | integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== 1083 | 1084 | validate-npm-package-license@^3.0.1: 1085 | version "3.0.4" 1086 | resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 1087 | integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 1088 | dependencies: 1089 | spdx-correct "^3.0.0" 1090 | spdx-expression-parse "^3.0.0" 1091 | 1092 | which-pm-runs@^1.0.0: 1093 | version "1.0.0" 1094 | resolved "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" 1095 | integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= 1096 | 1097 | which@^1.2.9: 1098 | version "1.3.1" 1099 | resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1100 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 1101 | dependencies: 1102 | isexe "^2.0.0" 1103 | 1104 | which@^2.0.1: 1105 | version "2.0.2" 1106 | resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1107 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1108 | dependencies: 1109 | isexe "^2.0.0" 1110 | 1111 | wrap-ansi@^6.2.0: 1112 | version "6.2.0" 1113 | resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" 1114 | integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== 1115 | dependencies: 1116 | ansi-styles "^4.0.0" 1117 | string-width "^4.1.0" 1118 | strip-ansi "^6.0.0" 1119 | 1120 | wrappy@1: 1121 | version "1.0.2" 1122 | resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1123 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1124 | 1125 | yaml@^1.7.2: 1126 | version "1.9.2" 1127 | resolved "https://registry.npmjs.org/yaml/-/yaml-1.9.2.tgz#f0cfa865f003ab707663e4f04b3956957ea564ed" 1128 | integrity sha512-HPT7cGGI0DuRcsO51qC1j9O16Dh1mZ2bnXwsi0jrSpsLz0WxOLSLXfkABVl6bZO629py3CU+OMJtpNHDLB97kg== 1129 | dependencies: 1130 | "@babel/runtime" "^7.9.2" 1131 | --------------------------------------------------------------------------------