Merge pull request #146 from napi-rs/serde

Serde
This commit is contained in:
LongYinan 2020-09-02 00:04:54 +08:00 committed by GitHub
commit 5a040872e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 1842 additions and 335 deletions

View file

@ -12,6 +12,7 @@ edition = "2018"
[features]
libuv = ["futures"]
tokio_rt = ["futures", "tokio", "once_cell"]
serde-json = ["serde", "serde_json"]
[dependencies]
napi-sys = { version = "0.4", path = "../sys" }
@ -29,6 +30,13 @@ optional = true
version = "1.4"
optional = true
[dependencies.serde]
version = "1"
optional = true
[dependencies.serde_json]
version = "1"
optional = true
[build-dependencies]
napi-build = { version = "0.2", path = "../build" }

View file

@ -11,12 +11,18 @@ use crate::js_values::*;
use crate::task::Task;
use crate::{sys, Error, NodeVersion, Result, Status};
#[cfg(all(feature = "serde-json"))]
use crate::js_values::{De, Ser};
#[cfg(all(any(feature = "libuv", feature = "tokio_rt"), napi4))]
use crate::promise;
#[cfg(all(feature = "tokio_rt", napi4))]
use crate::tokio_rt::{get_tokio_sender, Message};
#[cfg(all(feature = "libuv", napi4))]
use crate::uv;
#[cfg(all(feature = "serde-json"))]
use serde::de::DeserializeOwned;
#[cfg(all(feature = "serde-json"))]
use serde::Serialize;
#[cfg(all(feature = "libuv", napi4))]
use std::future::Future;
#[cfg(all(feature = "tokio_rt", napi4))]
@ -98,7 +104,7 @@ impl Env {
pub fn create_bigint_from_i64(&self, value: i64) -> Result<JsBigint> {
let mut raw_value = ptr::null_mut();
check_status(unsafe { sys::napi_create_bigint_int64(self.0, value, &mut raw_value) })?;
Ok(JsBigint::from_raw_unchecked(self.0, raw_value))
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
}
#[cfg(napi6)]
@ -107,7 +113,7 @@ impl Env {
pub fn create_bigint_from_u64(&self, value: u64) -> Result<JsBigint> {
let mut raw_value = ptr::null_mut();
check_status(unsafe { sys::napi_create_bigint_uint64(self.0, value, &mut raw_value) })?;
Ok(JsBigint::from_raw_unchecked(self.0, raw_value))
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
}
#[cfg(napi6)]
@ -116,6 +122,7 @@ impl Env {
/// The resulting BigInt will be negative when sign_bit is true.
pub fn create_bigint_from_words(&self, sign_bit: bool, words: Vec<u64>) -> Result<JsBigint> {
let mut raw_value = ptr::null_mut();
let len = words.len();
check_status(unsafe {
sys::napi_create_bigint_words(
self.0,
@ -123,12 +130,12 @@ impl Env {
true => 1,
false => 0,
},
words.len() as u64,
len as u64,
words.as_ptr(),
&mut raw_value,
)
})?;
Ok(JsBigint::from_raw_unchecked(self.0, raw_value))
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, len as _))
}
#[inline]
@ -608,6 +615,32 @@ impl Env {
Ok(JsObject::from_raw_unchecked(self.0, raw_promise))
}
#[cfg(feature = "serde-json")]
#[inline]
pub fn to_js_value<T>(&self, node: &T) -> Result<JsUnknown>
where
T: Serialize,
{
let s = Ser(self);
node.serialize(s).map(JsUnknown)
}
#[cfg(feature = "serde-json")]
#[inline]
pub fn from_js_value<T, V>(&self, value: V) -> Result<T>
where
T: DeserializeOwned + ?Sized,
V: NapiValue,
{
let value = Value {
env: self.0,
value: value.raw_value(),
value_type: ValueType::Unknown,
};
let mut de = De(&value);
T::deserialize(&mut de)
}
#[inline]
pub fn strict_equals<A: NapiValue, B: NapiValue>(&self, a: A, b: B) -> Result<bool> {
let mut result = false;

View file

@ -1,7 +1,14 @@
use std::convert::From;
use std::error::Error as StdError;
use std::fmt;
#[cfg(feature = "serde-json")]
use std::fmt::Display;
use std::os::raw::c_char;
use std::ptr;
#[cfg(feature = "serde-json")]
use serde::{de, ser};
use crate::{sys, Status};
pub type Result<T> = std::result::Result<T, Error>;
@ -12,6 +19,22 @@ pub struct Error {
pub reason: String,
}
impl StdError for Error {}
#[cfg(feature = "serde-json")]
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error::new(Status::InvalidArg, msg.to_string())
}
}
#[cfg(feature = "serde-json")]
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error::new(Status::InvalidArg, msg.to_string())
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}: {}", self.status, self.reason)
@ -82,6 +105,6 @@ pub fn check_status(code: sys::napi_status) -> Result<()> {
let status = Status::from(code);
match status {
Status::Ok => Ok(()),
_ => Err(Error::from_status(status)),
_ => Err(Error::new(status, "".to_owned())),
}
}

View file

@ -1,8 +1,9 @@
use std::convert::TryFrom;
use std::ptr;
use super::{JsObject, NapiValue, Value, ValueType};
use super::{JsObject, JsUnknown, NapiValue, Value, ValueType};
use crate::error::check_status;
use crate::{sys, Result};
use crate::{sys, Error, Result};
#[derive(Debug)]
pub struct JsArrayBuffer {
@ -46,3 +47,10 @@ impl NapiValue for JsArrayBuffer {
})
}
}
impl TryFrom<JsUnknown> for JsArrayBuffer {
type Error = Error;
fn try_from(value: JsUnknown) -> Result<JsArrayBuffer> {
JsArrayBuffer::from_raw(value.0.env, value.0.value)
}
}

View file

@ -1,12 +1,146 @@
use std::convert::TryFrom;
use std::ptr;
use super::{Error, Value};
use super::*;
use crate::error::check_status;
use crate::{sys, Result};
#[derive(Debug)]
pub struct JsBigint(pub(crate) Value);
pub struct JsBigint {
pub(crate) raw: Value,
pub word_count: u64,
}
impl JsBigint {
pub(crate) fn from_raw_unchecked(
env: sys::napi_env,
value: sys::napi_value,
word_count: u64,
) -> Self {
Self {
raw: Value {
env,
value,
value_type: ValueType::Object,
},
word_count,
}
}
#[inline]
pub fn into_unknown(self) -> Result<JsUnknown> {
JsUnknown::from_raw(self.raw.env, self.raw.value)
}
#[inline]
pub fn coerce_to_number(self) -> Result<JsNumber> {
let mut new_raw_value = ptr::null_mut();
let status =
unsafe { sys::napi_coerce_to_number(self.raw.env, self.raw.value, &mut new_raw_value) };
check_status(status)?;
Ok(JsNumber(Value {
env: self.raw.env,
value: new_raw_value,
value_type: ValueType::Number,
}))
}
#[inline]
pub fn coerce_to_string(self) -> Result<JsString> {
let mut new_raw_value = ptr::null_mut();
let status =
unsafe { sys::napi_coerce_to_string(self.raw.env, self.raw.value, &mut new_raw_value) };
check_status(status)?;
Ok(JsString(Value {
env: self.raw.env,
value: new_raw_value,
value_type: ValueType::String,
}))
}
#[inline]
pub fn coerce_to_object(self) -> Result<JsObject> {
let mut new_raw_value = ptr::null_mut();
let status =
unsafe { sys::napi_coerce_to_object(self.raw.env, self.raw.value, &mut new_raw_value) };
check_status(status)?;
Ok(JsObject(Value {
env: self.raw.env,
value: new_raw_value,
value_type: ValueType::Object,
}))
}
#[inline]
#[cfg(napi5)]
pub fn is_date(&self) -> Result<bool> {
let mut is_date = true;
let status = unsafe { sys::napi_is_date(self.raw.env, self.raw.value, &mut is_date) };
check_status(status)?;
Ok(is_date)
}
#[inline]
pub fn is_error(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe { sys::napi_is_error(self.raw.env, self.raw.value, &mut result) })?;
Ok(result)
}
#[inline]
pub fn is_typedarray(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe { sys::napi_is_typedarray(self.raw.env, self.raw.value, &mut result) })?;
Ok(result)
}
#[inline]
pub fn is_dataview(&self) -> Result<bool> {
let mut result = false;
check_status(unsafe { sys::napi_is_dataview(self.raw.env, self.raw.value, &mut result) })?;
Ok(result)
}
#[inline]
pub fn instanceof<Constructor: NapiValue>(&self, constructor: Constructor) -> Result<bool> {
let mut result = false;
check_status(unsafe {
sys::napi_instanceof(
self.raw.env,
self.raw.value,
constructor.raw_value(),
&mut result,
)
})?;
Ok(result)
}
}
impl NapiValue for JsBigint {
fn raw_value(&self) -> sys::napi_value {
self.raw.value
}
fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
let mut word_count: u64 = 0;
check_status(unsafe {
sys::napi_get_value_bigint_words(
env,
value,
ptr::null_mut(),
&mut word_count,
ptr::null_mut(),
)
})?;
Ok(JsBigint {
raw: Value {
env,
value,
value_type: ValueType::Bigint,
},
word_count,
})
}
}
/// The BigInt will be converted losslessly when the value is over what an int64 could hold.
impl TryFrom<JsBigint> for i64 {
@ -28,38 +162,26 @@ impl TryFrom<JsBigint> for u64 {
impl JsBigint {
/// https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_words
pub fn get_words(&self, sign_bit: bool) -> Result<Vec<u64>> {
let mut word_count: u64 = 0;
#[inline]
pub fn get_words(&mut self) -> Result<(bool, Vec<u64>)> {
let mut words: Vec<u64> = Vec::with_capacity(self.word_count as usize);
let word_count = &mut self.word_count;
let mut sign_bit = 0;
check_status(unsafe {
sys::napi_get_value_bigint_words(
self.0.env,
self.0.value,
ptr::null_mut(),
&mut word_count,
ptr::null_mut(),
)
})?;
let mut words: Vec<u64> = Vec::with_capacity(word_count as usize);
let mut sign_bit = match sign_bit {
true => 1,
false => 0,
};
check_status(unsafe {
sys::napi_get_value_bigint_words(
self.0.env,
self.0.value,
self.raw.env,
self.raw.value,
&mut sign_bit,
&mut word_count,
word_count,
words.as_mut_ptr(),
)
})?;
unsafe {
words.set_len(word_count as usize);
words.set_len(self.word_count as usize);
};
Ok(words)
Ok((sign_bit == 1, words))
}
#[inline]
@ -67,7 +189,7 @@ impl JsBigint {
let mut val: u64 = 0;
let mut loss = false;
check_status(unsafe {
sys::napi_get_value_bigint_uint64(self.0.env, self.0.value, &mut val, &mut loss)
sys::napi_get_value_bigint_uint64(self.raw.env, self.raw.value, &mut val, &mut loss)
})?;
Ok((val, loss))
@ -78,8 +200,29 @@ impl JsBigint {
let mut val: i64 = 0;
let mut loss: bool = false;
check_status(unsafe {
sys::napi_get_value_bigint_int64(self.0.env, self.0.value, &mut val, &mut loss)
sys::napi_get_value_bigint_int64(self.raw.env, self.raw.value, &mut val, &mut loss)
})?;
Ok((val, loss))
}
#[inline]
pub fn get_i128(&mut self) -> Result<(i128, bool)> {
let (signed, words) = self.get_words()?;
let len = words.len();
let i128_words: [i64; 2] = [words[0] as _, words[1] as _];
let mut val = unsafe { ptr::read(i128_words.as_ptr() as *const i128) };
if signed {
val = -val;
}
Ok((val, len > 2))
}
#[inline]
pub fn get_u128(&mut self) -> Result<(bool, u128, bool)> {
let (signed, words) = self.get_words()?;
let len = words.len();
let u128_words: [u64; 2] = [words[0], words[1]];
let val = unsafe { ptr::read(u128_words.as_ptr() as *const u128) };
Ok((signed, val, len > 2))
}
}

View file

@ -1,10 +1,11 @@
use std::convert::TryFrom;
use std::ops::Deref;
use std::ptr;
use std::slice;
use super::{JsObject, JsUnknown, NapiValue, Value, ValueType};
use crate::error::check_status;
use crate::{sys, Result};
use crate::{sys, Error, Result};
#[derive(Debug)]
pub struct JsBuffer {
@ -42,8 +43,7 @@ impl NapiValue for JsBuffer {
fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
let mut data = ptr::null_mut();
let mut len: u64 = 0;
let status = unsafe { sys::napi_get_buffer_info(env, value, &mut data, &mut len) };
check_status(status)?;
check_status(unsafe { sys::napi_get_buffer_info(env, value, &mut data, &mut len) })?;
Ok(JsBuffer {
value: JsObject(Value {
env,
@ -68,3 +68,10 @@ impl Deref for JsBuffer {
self.data
}
}
impl TryFrom<JsUnknown> for JsBuffer {
type Error = Error;
fn try_from(value: JsUnknown) -> Result<JsBuffer> {
JsBuffer::from_raw(value.0.env, value.0.value)
}
}

358
napi/src/js_values/de.rs Normal file
View file

@ -0,0 +1,358 @@
use std::convert::TryInto;
use serde::de::Visitor;
use serde::de::{DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, VariantAccess};
use super::{type_of, NapiValue, Value, ValueType};
#[cfg(napi6)]
use crate::JsBigint;
use crate::{Error, JsBoolean, JsBuffer, JsNumber, JsObject, JsString, JsUnknown, Result, Status};
pub(crate) struct De<'env>(pub(crate) &'env Value);
#[doc(hidden)]
impl<'x, 'de, 'env> serde::de::Deserializer<'x> for &'de mut De<'env> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'x>,
{
let js_value_type = type_of(self.0.env, self.0.value)?;
match js_value_type {
ValueType::Null | ValueType::Undefined => visitor.visit_unit(),
ValueType::Boolean => {
let js_boolean = JsBoolean::from_raw_unchecked(self.0.env, self.0.value);
visitor.visit_bool(js_boolean.get_value()?)
}
ValueType::Number => {
let js_number: f64 = JsNumber::from_raw_unchecked(self.0.env, self.0.value).try_into()?;
if js_number.trunc() == js_number {
visitor.visit_i64(js_number as i64)
} else {
visitor.visit_f64(js_number)
}
}
ValueType::String => {
let js_string = JsString::from_raw_unchecked(self.0.env, self.0.value);
visitor.visit_str(js_string.as_str()?)
}
ValueType::Object => {
let js_object = JsObject::from_raw_unchecked(self.0.env, self.0.value);
if js_object.is_array()? {
let mut deserializer =
JsArrayAccess::new(&js_object, js_object.get_array_length_unchecked()?);
visitor.visit_seq(&mut deserializer)
} else if js_object.is_buffer()? {
visitor.visit_bytes(JsBuffer::from_raw(self.0.env, self.0.value)?.data)
} else {
let mut deserializer = JsObjectAccess::new(&js_object)?;
visitor.visit_map(&mut deserializer)
}
}
#[cfg(napi6)]
ValueType::Bigint => {
let mut js_bigint = JsBigint::from_raw(self.0.env, self.0.value)?;
let (signed, v, _loss) = js_bigint.get_u128()?;
if signed {
visitor.visit_i128(-(v as i128))
} else {
visitor.visit_u128(v)
}
}
ValueType::External | ValueType::Function | ValueType::Symbol => Err(Error::new(
Status::InvalidArg,
format!("typeof {:?} value could not be deserialized", js_value_type),
)),
ValueType::Unknown => unreachable!(),
}
}
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'x>,
{
visitor.visit_bytes(JsBuffer::from_raw(self.0.env, self.0.value)?.data)
}
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'x>,
{
visitor.visit_bytes(JsBuffer::from_raw(self.0.env, self.0.value)?.data)
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'x>,
{
match type_of(self.0.env, self.0.value)? {
ValueType::Undefined | ValueType::Null => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'x>,
{
let js_value_type = type_of(self.0.env, self.0.value)?;
match js_value_type {
ValueType::String => visitor.visit_enum(JsEnumAccess::new(
JsString::from_raw_unchecked(self.0.env, self.0.value)
.as_str()?
.to_owned(),
None,
)),
ValueType::Object => {
let js_object = JsObject::from_raw_unchecked(self.0.env, self.0.value);
let properties = js_object.get_property_names::<JsObject>()?;
let property_len = properties.get_array_length_unchecked()?;
if property_len != 1 {
Err(Error::new(
Status::InvalidArg,
format!(
"object key length: {}, can not deserialize to Enum",
property_len
),
))
} else {
let key = properties.get_index::<JsString>(0)?;
let value: JsUnknown = js_object.get_property(&key)?;
visitor.visit_enum(JsEnumAccess::new(key.as_str()?.to_owned(), Some(&value.0)))
}
}
_ => Err(Error::new(
Status::InvalidArg,
format!(
"{:?} type could not deserialize to Enum type",
js_value_type
),
)),
}
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'x>,
{
visitor.visit_unit()
}
forward_to_deserialize_any! {
<V: Visitor<'x>>
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
unit unit_struct seq tuple tuple_struct map struct identifier
newtype_struct
}
}
#[doc(hidden)]
pub(crate) struct JsEnumAccess<'env> {
variant: String,
value: Option<&'env Value>,
}
#[doc(hidden)]
impl<'env> JsEnumAccess<'env> {
fn new(variant: String, value: Option<&'env Value>) -> Self {
Self { variant, value }
}
}
#[doc(hidden)]
impl<'de, 'env> EnumAccess<'de> for JsEnumAccess<'env> {
type Error = Error;
type Variant = JsVariantAccess<'env>;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: DeserializeSeed<'de>,
{
use serde::de::IntoDeserializer;
let variant = self.variant.into_deserializer();
let variant_access = JsVariantAccess { value: self.value };
seed.deserialize(variant).map(|v| (v, variant_access))
}
}
#[doc(hidden)]
pub(crate) struct JsVariantAccess<'env> {
value: Option<&'env Value>,
}
#[doc(hidden)]
impl<'de, 'env> VariantAccess<'de> for JsVariantAccess<'env> {
type Error = Error;
fn unit_variant(self) -> Result<()> {
match self.value {
Some(val) => {
let mut deserializer = De(val);
serde::de::Deserialize::deserialize(&mut deserializer)
}
None => Ok(()),
}
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
where
T: DeserializeSeed<'de>,
{
match self.value {
Some(val) => {
let mut deserializer = De(val);
seed.deserialize(&mut deserializer)
}
None => Err(serde::de::Error::invalid_type(
Unexpected::UnitVariant,
&"newtype variant",
)),
}
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self.value {
Some(js_value) => {
let js_object = JsObject::from_raw(js_value.env, js_value.value)?;
if js_object.is_array()? {
let mut deserializer =
JsArrayAccess::new(&js_object, js_object.get_array_length_unchecked()?);
visitor.visit_seq(&mut deserializer)
} else {
Err(serde::de::Error::invalid_type(
Unexpected::Other("JsValue"),
&"tuple variant",
))
}
}
None => Err(serde::de::Error::invalid_type(
Unexpected::UnitVariant,
&"tuple variant",
)),
}
}
fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self.value {
Some(js_value) => {
if let Ok(val) = JsObject::from_raw(js_value.env, js_value.value) {
let mut deserializer = JsObjectAccess::new(&val)?;
visitor.visit_map(&mut deserializer)
} else {
Err(serde::de::Error::invalid_type(
Unexpected::Other("JsValue"),
&"struct variant",
))
}
}
_ => Err(serde::de::Error::invalid_type(
Unexpected::UnitVariant,
&"struct variant",
)),
}
}
}
#[doc(hidden)]
struct JsArrayAccess<'env> {
input: &'env JsObject,
idx: u32,
len: u32,
}
#[doc(hidden)]
impl<'env> JsArrayAccess<'env> {
fn new(input: &'env JsObject, len: u32) -> Self {
Self { input, idx: 0, len }
}
}
#[doc(hidden)]
impl<'de, 'env> SeqAccess<'de> for JsArrayAccess<'env> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
where
T: DeserializeSeed<'de>,
{
if self.idx >= self.len {
return Ok(None);
}
let v = self.input.get_index::<JsUnknown>(self.idx)?;
self.idx += 1;
let mut de = De(&v.0);
seed.deserialize(&mut de).map(Some)
}
}
#[doc(hidden)]
pub(crate) struct JsObjectAccess<'env> {
value: &'env JsObject,
properties: JsObject,
idx: u32,
property_len: u32,
}
#[doc(hidden)]
impl<'env> JsObjectAccess<'env> {
fn new(value: &'env JsObject) -> Result<Self> {
let properties = value.get_property_names::<JsObject>()?;
let property_len = properties.get_array_length_unchecked()?;
Ok(Self {
value,
properties,
idx: 0,
property_len,
})
}
}
#[doc(hidden)]
impl<'de, 'env> MapAccess<'de> for JsObjectAccess<'env> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
if self.idx >= self.property_len {
return Ok(None);
}
let prop_name = self.properties.get_index::<JsUnknown>(self.idx)?;
let mut de = De(&prop_name.0);
seed.deserialize(&mut de).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
if self.idx >= self.property_len {
return Err(Error::new(
Status::InvalidArg,
format!("Index:{} out of range: {}", self.property_len, self.idx),
));
}
let prop_name = self.properties.get_index::<JsString>(self.idx)?;
let value: JsUnknown = self.value.get_property(&prop_name)?;
self.idx += 1;
let mut de = De(&value.0);
let res = seed.deserialize(&mut de)?;
Ok(res)
}
}

View file

@ -1,9 +1,14 @@
use std::convert::From;
use std::convert::{From, TryFrom};
use std::ptr;
use crate::error::check_status;
use crate::{sys, Error, Result, Status};
#[cfg(feature = "serde-json")]
mod de;
#[cfg(feature = "serde-json")]
mod ser;
mod arraybuffer;
#[cfg(napi6)]
mod bigint;
@ -27,10 +32,14 @@ pub use bigint::JsBigint;
pub use boolean::JsBoolean;
pub use buffer::JsBuffer;
pub use class_property::Property;
#[cfg(feature = "serde-json")]
pub(crate) use de::De;
pub use either::Either;
pub use function::JsFunction;
pub use number::JsNumber;
pub use object::JsObject;
#[cfg(feature = "serde-json")]
pub(crate) use ser::Ser;
pub use string::JsString;
pub(crate) use tagged_object::TaggedObject;
pub use undefined::JsUndefined;
@ -94,6 +103,13 @@ macro_rules! impl_napi_value_trait {
})
}
}
impl TryFrom<JsUnknown> for $js_value {
type Error = Error;
fn try_from(value: JsUnknown) -> Result<$js_value> {
$js_value::from_raw(value.0.env, value.0.value)
}
}
};
}
@ -204,8 +220,6 @@ impl_js_value_methods!(JsString);
impl_js_value_methods!(JsObject);
impl_js_value_methods!(JsFunction);
impl_js_value_methods!(JsExternal);
#[cfg(napi6)]
impl_js_value_methods!(JsBigint);
impl_js_value_methods!(JsSymbol);
use ValueType::*;
@ -218,8 +232,6 @@ impl_napi_value_trait!(JsString, String);
impl_napi_value_trait!(JsObject, Object);
impl_napi_value_trait!(JsFunction, Function);
impl_napi_value_trait!(JsExternal, External);
#[cfg(napi6)]
impl_napi_value_trait!(JsBigint, Bigint);
impl_napi_value_trait!(JsSymbol, Symbol);
impl NapiValue for JsUnknown {

View file

@ -21,28 +21,32 @@ impl JsObject {
key: JsNumber,
value: V,
) -> Result<()> {
let status =
unsafe { sys::napi_set_property(self.0.env, self.0.value, key.0.value, value.raw_value()) };
check_status(status)?;
Ok(())
check_status(unsafe {
sys::napi_set_property(self.0.env, self.0.value, key.0.value, value.raw_value())
})
}
pub fn set_named_property<T: NapiValue>(&mut self, name: &str, value: T) -> Result<()> {
let key = CString::new(name)?;
let status = unsafe {
check_status(unsafe {
sys::napi_set_named_property(self.0.env, self.0.value, key.as_ptr(), value.raw_value())
};
check_status(status)?;
Ok(())
})
}
pub fn get_named_property<T: NapiValue>(&self, name: &str) -> Result<T> {
let key = CString::new(name)?;
let mut raw_value = ptr::null_mut();
let status = unsafe {
check_status(unsafe {
sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value)
};
check_status(status)?;
})?;
T::from_raw(self.0.env, raw_value)
}
pub fn get_property<K: NapiValue, T: NapiValue>(&self, key: &K) -> Result<T> {
let mut raw_value = ptr::null_mut();
check_status(unsafe {
sys::napi_get_property(self.0.env, self.0.value, key.raw_value(), &mut raw_value)
})?;
T::from_raw(self.0.env, raw_value)
}
@ -59,22 +63,21 @@ impl JsObject {
pub fn get_index<T: NapiValue>(&self, index: u32) -> Result<T> {
let mut raw_value = ptr::null_mut();
let status = unsafe { sys::napi_get_element(self.0.env, self.0.value, index, &mut raw_value) };
check_status(status)?;
check_status(unsafe {
sys::napi_get_element(self.0.env, self.0.value, index, &mut raw_value)
})?;
T::from_raw(self.0.env, raw_value)
}
pub fn is_array(&self) -> Result<bool> {
let mut is_array = false;
let status = unsafe { sys::napi_is_array(self.0.env, self.0.value, &mut is_array) };
check_status(status)?;
check_status(unsafe { sys::napi_is_array(self.0.env, self.0.value, &mut is_array) })?;
Ok(is_array)
}
pub fn is_buffer(&self) -> Result<bool> {
let mut is_buffer = false;
let status = unsafe { sys::napi_is_buffer(self.0.env, self.0.value, &mut is_buffer) };
check_status(status)?;
check_status(unsafe { sys::napi_is_buffer(self.0.env, self.0.value, &mut is_buffer) })?;
Ok(is_buffer)
}
@ -89,9 +92,13 @@ impl JsObject {
"Object is not array".to_owned(),
));
}
self.get_array_length_unchecked()
}
#[inline]
pub fn get_array_length_unchecked(&self) -> Result<u32> {
let mut length: u32 = 0;
let status = unsafe { sys::napi_get_array_length(self.0.env, self.raw_value(), &mut length) };
check_status(status)?;
check_status(unsafe { sys::napi_get_array_length(self.0.env, self.raw_value(), &mut length) })?;
Ok(length)
}
}

510
napi/src/js_values/ser.rs Normal file
View file

@ -0,0 +1,510 @@
use std::result::Result as StdResult;
#[cfg(napi6)]
use std::slice;
use serde::{ser, Serialize, Serializer};
use super::*;
use crate::{Env, Error, Result};
pub(crate) struct Ser<'env>(pub(crate) &'env Env);
impl<'env> Ser<'env> {
fn new(env: &'env Env) -> Self {
Self(&env)
}
}
impl<'env> Serializer for Ser<'env> {
type Ok = Value;
type Error = Error;
type SerializeSeq = SeqSerializer;
type SerializeTuple = SeqSerializer;
type SerializeTupleStruct = SeqSerializer;
type SerializeTupleVariant = SeqSerializer;
type SerializeMap = MapSerializer;
type SerializeStruct = StructSerializer;
type SerializeStructVariant = StructSerializer;
#[inline]
fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
self.0.get_boolean(v).map(|js_value| js_value.0)
}
#[inline]
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
self
.0
.create_buffer_with_data(v.to_owned())
.map(|js_value| js_value.value.0)
}
#[inline]
fn serialize_char(self, v: char) -> Result<Self::Ok> {
let mut b = [0; 4];
let result = v.encode_utf8(&mut b);
self.0.create_string(result).map(|js_string| js_string.0)
}
#[inline]
fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
self.0.create_double(v as _).map(|js_number| js_number.0)
}
#[inline]
fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
self.0.create_double(v).map(|js_number| js_number.0)
}
#[inline]
fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
self.0.create_int32(v as _).map(|js_number| js_number.0)
}
#[inline]
fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
self.0.create_int32(v).map(|js_number| js_number.0)
}
#[inline]
fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
self.0.create_int64(v).map(|js_number| js_number.0)
}
#[inline]
fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
self.0.create_int32(v as _).map(|js_number| js_number.0)
}
#[inline]
fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
self.0.create_uint32(v as _).map(|js_number| js_number.0)
}
#[inline]
fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
self.0.create_uint32(v as _).map(|js_number| js_number.0)
}
#[inline]
fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
self.0.create_uint32(v).map(|js_number| js_number.0)
}
#[cfg(all(any(napi2, napi3, napi4, napi5), not(napi6)))]
#[inline]
fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
self.0.create_int64(v as _).map(|js_number| js_number.0)
}
#[cfg(napi6)]
#[inline]
fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
self
.0
.create_bigint_from_u64(v)
.map(|js_number| js_number.raw)
}
#[cfg(all(any(napi2, napi3, napi4, napi5), not(napi6)))]
#[inline]
fn serialize_u128(self, v: u128) -> Result<Self::Ok> {
self.0.create_string(v.to_string().as_str()).map(|v| v.0)
}
#[cfg(napi6)]
#[inline]
fn serialize_u128(self, v: u128) -> Result<Self::Ok> {
let words_ref = &v as *const _;
let words = unsafe { slice::from_raw_parts(words_ref as *const u64, 2) };
self
.0
.create_bigint_from_words(false, words.to_vec())
.map(|v| v.raw)
}
#[cfg(all(any(napi2, napi3, napi4, napi5), not(napi6)))]
#[inline]
fn serialize_i128(self, v: i128) -> Result<Self::Ok> {
self.0.create_string(v.to_string().as_str()).map(|v| v.0)
}
#[cfg(napi6)]
#[inline]
fn serialize_i128(self, v: i128) -> Result<Self::Ok> {
let words_ref = &(v as u128) as *const _;
let words = unsafe { slice::from_raw_parts(words_ref as *const u64, 2) };
self
.0
.create_bigint_from_words(v < 0, words.to_vec())
.map(|v| v.raw)
}
#[inline]
fn serialize_unit(self) -> Result<Self::Ok> {
self.0.get_null().map(|null| null.0)
}
#[inline]
fn serialize_none(self) -> Result<Self::Ok> {
self.0.get_null().map(|null| null.0)
}
#[inline]
fn serialize_str(self, v: &str) -> Result<Self::Ok> {
self.0.create_string(v).map(|string| string.0)
}
#[inline]
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok>
where
T: Serialize,
{
value.serialize(self)
}
#[inline]
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
let env = self.0;
let key = env.create_string("")?;
let obj = env.create_object()?;
Ok(MapSerializer { key, obj })
}
#[inline]
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
let array = self.0.create_array_with_length(len.unwrap_or(0))?;
Ok(SeqSerializer {
current_index: 0,
array,
})
}
#[inline]
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant> {
let env = self.0;
let array = env.create_array_with_length(len)?;
let mut object = env.create_object()?;
object.set_named_property(
variant,
JsObject(Value {
value: array.0.value,
env: array.0.env,
value_type: ValueType::Object,
}),
)?;
Ok(SeqSerializer {
current_index: 0,
array,
})
}
#[inline]
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
self.0.get_null().map(|null| null.0)
}
#[inline]
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok> {
self.0.create_string(variant).map(|string| string.0)
}
#[inline]
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> Result<Self::Ok>
where
T: Serialize,
{
value.serialize(self)
}
#[inline]
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Self::Ok>
where
T: Serialize,
{
let mut obj = self.0.create_object()?;
obj.set_named_property(variant, JsUnknown(value.serialize(self)?))?;
Ok(obj.0)
}
#[inline]
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
Ok(SeqSerializer {
array: self.0.create_array_with_length(len)?,
current_index: 0,
})
}
#[inline]
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct> {
Ok(SeqSerializer {
array: self.0.create_array_with_length(len)?,
current_index: 0,
})
}
#[inline]
fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
Ok(StructSerializer {
obj: self.0.create_object()?,
})
}
#[inline]
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
let mut outer = self.0.create_object()?;
let inner = self.0.create_object()?;
outer.set_named_property(
variant,
JsObject(Value {
env: inner.0.env,
value: inner.0.value,
value_type: ValueType::Object,
}),
)?;
Ok(StructSerializer {
obj: self.0.create_object()?,
})
}
}
pub struct SeqSerializer {
array: JsObject,
current_index: usize,
}
impl ser::SerializeSeq for SeqSerializer {
type Ok = Value;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> StdResult<(), Self::Error>
where
T: Serialize,
{
let env = Env::from_raw(self.array.0.env);
self.array.set_index(
self.current_index,
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
self.current_index = self.current_index + 1;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
Ok(self.array.0)
}
}
#[doc(hidden)]
impl ser::SerializeTuple for SeqSerializer {
type Ok = Value;
type Error = Error;
#[inline]
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> StdResult<(), Self::Error>
where
T: Serialize,
{
let env = Env::from_raw(self.array.0.env);
self.array.set_index(
self.current_index,
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
self.current_index = self.current_index + 1;
Ok(())
}
#[inline]
fn end(self) -> StdResult<Self::Ok, Self::Error> {
Ok(self.array.0)
}
}
#[doc(hidden)]
impl ser::SerializeTupleStruct for SeqSerializer {
type Ok = Value;
type Error = Error;
#[inline]
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> StdResult<(), Self::Error>
where
T: Serialize,
{
let env = Env::from_raw(self.array.0.env);
self.array.set_index(
self.current_index,
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
self.current_index = self.current_index + 1;
Ok(())
}
#[inline]
fn end(self) -> StdResult<Self::Ok, Self::Error> {
Ok(self.array.0)
}
}
#[doc(hidden)]
impl ser::SerializeTupleVariant for SeqSerializer {
type Ok = Value;
type Error = Error;
#[inline]
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> StdResult<(), Self::Error>
where
T: Serialize,
{
let env = Env::from_raw(self.array.0.env);
self.array.set_index(
self.current_index,
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
self.current_index = self.current_index + 1;
Ok(())
}
#[inline]
fn end(self) -> Result<Self::Ok> {
Ok(self.array.0)
}
}
pub struct MapSerializer {
key: JsString,
obj: JsObject,
}
#[doc(hidden)]
impl ser::SerializeMap for MapSerializer {
type Ok = Value;
type Error = Error;
#[inline]
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> StdResult<(), Self::Error>
where
T: Serialize,
{
let env = Env::from_raw(self.obj.0.env);
self.key = JsString(key.serialize(Ser::new(&env))?);
Ok(())
}
#[inline]
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> StdResult<(), Self::Error>
where
T: Serialize,
{
let env = Env::from_raw(self.obj.0.env);
self.obj.set_property(
JsString(Value {
env: self.key.0.env,
value: self.key.0.value,
value_type: ValueType::String,
}),
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
Ok(())
}
#[inline]
fn serialize_entry<K: ?Sized, V: ?Sized>(
&mut self,
key: &K,
value: &V,
) -> StdResult<(), Self::Error>
where
K: Serialize,
V: Serialize,
{
let env = Env::from_raw(self.obj.0.env);
self.obj.set_property(
JsString(key.serialize(Ser::new(&env))?),
JsUnknown(value.serialize(Ser::new(&env))?),
)?;
Ok(())
}
#[inline]
fn end(self) -> Result<Self::Ok> {
Ok(self.obj.0)
}
}
pub struct StructSerializer {
obj: JsObject,
}
#[doc(hidden)]
impl ser::SerializeStruct for StructSerializer {
type Ok = Value;
type Error = Error;
#[inline]
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> StdResult<(), Error>
where
T: Serialize,
{
let env = Env::from_raw(self.obj.0.env);
self
.obj
.set_named_property(key, JsUnknown(value.serialize(Ser::new(&env))?))?;
Ok(())
}
#[inline]
fn end(self) -> Result<Self::Ok> {
Ok(self.obj.0)
}
}
#[doc(hidden)]
impl ser::SerializeStructVariant for StructSerializer {
type Ok = Value;
type Error = Error;
#[inline]
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> StdResult<(), Error>
where
T: Serialize,
{
let env = Env::from_raw(self.obj.0.env);
self
.obj
.set_named_property(key, JsUnknown(value.serialize(Ser::new(&env))?))?;
Ok(())
}
#[inline]
fn end(self) -> Result<Self::Ok> {
Ok(self.obj.0)
}
}

View file

@ -47,6 +47,30 @@ impl JsString {
}
}
#[inline]
pub fn chars(&self) -> Result<&[char]> {
let mut written_char_count: u64 = 0;
let len = self.len()? + 1;
let mut result = Vec::with_capacity(len);
unsafe {
let status = sys::napi_get_value_string_utf8(
self.0.env,
self.0.value,
result.as_mut_ptr(),
len as u64,
&mut written_char_count,
);
check_status(status)?;
let ptr = result.as_ptr();
mem::forget(result);
Ok(slice::from_raw_parts(
ptr as *const char,
written_char_count as usize,
))
}
}
pub fn as_str(&self) -> Result<&str> {
str::from_utf8(self.get_ref()?)
.map_err(|e| Error::new(Status::GenericFailure, format!("{:?}", e)))

View file

@ -2,7 +2,7 @@ use crate::sys;
use super::ValueType;
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
pub struct Value {
pub env: sys::napi_env,
pub value: sys::napi_value,

View file

@ -88,6 +88,10 @@ pub use version::NodeVersion;
#[cfg(all(feature = "tokio_rt", napi4))]
pub use tokio_rt::shutdown as shutdown_tokio_rt;
#[cfg(feature = "serde-json")]
#[macro_use]
extern crate serde;
/// register nodejs module
///
/// ## Example

View file

@ -1,3 +1,4 @@
use std::convert::Into;
use std::os::raw::{c_char, c_void};
use std::ptr;
@ -7,6 +8,44 @@ use crate::{sys, Env, JsFunction, JsUnknown, Result};
use sys::napi_threadsafe_function_call_mode;
use sys::napi_threadsafe_function_release_mode;
#[repr(u8)]
pub enum ThreadsafeFunctionCallMode {
NonBlocking,
Blocking,
}
#[repr(u8)]
pub enum ThreadsafeFunctionReleaseMode {
Release,
Abort,
}
impl Into<napi_threadsafe_function_call_mode> for ThreadsafeFunctionCallMode {
fn into(self) -> napi_threadsafe_function_call_mode {
match self {
ThreadsafeFunctionCallMode::Blocking => {
napi_threadsafe_function_call_mode::napi_tsfn_blocking
}
ThreadsafeFunctionCallMode::NonBlocking => {
napi_threadsafe_function_call_mode::napi_tsfn_nonblocking
}
}
}
}
impl Into<napi_threadsafe_function_release_mode> for ThreadsafeFunctionReleaseMode {
fn into(self) -> napi_threadsafe_function_release_mode {
match self {
ThreadsafeFunctionReleaseMode::Release => {
napi_threadsafe_function_release_mode::napi_tsfn_release
}
ThreadsafeFunctionReleaseMode::Abort => {
napi_threadsafe_function_release_mode::napi_tsfn_abort
}
}
}
}
pub trait ToJs: Copy + Clone {
type Output;
@ -25,17 +64,9 @@ pub trait ToJs: Copy + Clone {
/// use std::thread;
/// use napi::{
/// Number, Result, Env, CallContext, JsUndefined, JsFunction,
/// sys::{
/// napi_threadsafe_function_call_mode::{
/// napi_tsfn_blocking,
/// },
/// napi_threadsafe_function_release_mode::{
/// napi_tsfn_release,
/// }
/// }
/// };
/// use napi::threadsafe_function::{
/// ToJs, ThreadsafeFunction,
/// ToJs, ThreadsafeFunction, ThreadsafeFunctionCallMode, ThreadsafeFunctionReleaseMode,
/// };
///
/// // Define a struct for handling the data passed from `ThreadsafeFunction::call`
@ -67,12 +98,12 @@ pub trait ToJs: Copy + Clone {
/// thread::spawn(move || {
/// let output: u8 = 42;
/// // It's okay to call a threadsafe function multiple times.
/// tsfn.call(Ok(output), napi_tsfn_blocking).unwrap();
/// tsfn.call(Ok(output), napi_tsfn_blocking).unwrap();
/// tsfn.call(Ok(output), ThreadsafeFunctionCallMode::Blocking).unwrap();
/// tsfn.call(Ok(output), ThreadsafeFunctionCallMode::Blocking).unwrap();
/// // We should call `ThreadsafeFunction::release` manually when we don't
/// // need the instance anymore, or it will prevent Node.js from exiting
/// // automatically and possibly cause memory leaks.
/// tsfn.release(napi_tsfn_release).unwrap();
/// tsfn.release(ThreadsafeFunctionReleaseMode::Release).unwrap();
/// });
///
/// ctx.env.get_undefined()
@ -137,16 +168,12 @@ impl<T: ToJs> ThreadsafeFunction<T> {
/// See [napi_call_threadsafe_function](https://nodejs.org/api/n-api.html#n_api_napi_call_threadsafe_function)
/// for more information.
pub fn call(
&self,
value: Result<T::Output>,
mode: napi_threadsafe_function_call_mode,
) -> Result<()> {
pub fn call(&self, value: Result<T::Output>, mode: ThreadsafeFunctionCallMode) -> Result<()> {
check_status(unsafe {
sys::napi_call_threadsafe_function(
self.raw_value,
Box::into_raw(Box::from(value)) as *mut _ as *mut c_void,
mode,
mode.into(),
)
})
}
@ -159,8 +186,8 @@ impl<T: ToJs> ThreadsafeFunction<T> {
/// See [napi_release_threadsafe_function](https://nodejs.org/api/n-api.html#n_api_napi_release_threadsafe_function)
/// for more information.
pub fn release(&self, mode: napi_threadsafe_function_release_mode) -> Result<()> {
check_status(unsafe { sys::napi_release_threadsafe_function(self.raw_value, mode) })
pub fn release(&self, mode: ThreadsafeFunctionReleaseMode) -> Result<()> {
check_status(unsafe { sys::napi_release_threadsafe_function(self.raw_value, mode.into()) })
}
/// See [napi_ref_threadsafe_function](https://nodejs.org/api/n-api.html#n_api_napi_ref_threadsafe_function)

View file

@ -33,7 +33,7 @@
},
"homepage": "https://github.com/napi-rs/napi-rs#readme",
"dependencies": {
"clipanion": "^2.4.4",
"clipanion": "^2.5.0",
"inquirer": "^7.3.3",
"toml": "^3.0.0"
},
@ -58,13 +58,13 @@
},
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@swc-node/register": "^0.4.2",
"@swc-node/register": "^0.4.5",
"@types/inquirer": "^7.3.1",
"@types/node": "^14.6.0",
"@typescript-eslint/eslint-plugin": "^4.0.0",
"@typescript-eslint/parser": "^3.10.1",
"@types/node": "^14.6.2",
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"ava": "^3.12.1",
"eslint": "^7.7.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^3.1.4",
@ -78,7 +78,7 @@
"typescript": "^4.0.2"
},
"optionalDependencies": {
"@swc-node/core-linux-musl": "^0.6.0",
"@swc-node/core-linux-musl": "^0.6.1",
"tslib": "^2.0.1"
}
}

View file

@ -9,8 +9,12 @@ crate-type = ["cdylib"]
[dependencies]
futures = "0.3"
napi = { path = "../napi", features = ["libuv", "tokio_rt"] }
napi = { path = "../napi", features = ["libuv", "tokio_rt", "serde-json"] }
napi-derive = { path = "../napi-derive" }
serde = "1"
serde_bytes = "0.11"
serde_derive = "1"
serde_json = "1"
tokio = { version = "0.2", features = ["default", "fs"]}
[build-dependencies]

View file

@ -1,2 +1 @@
// @ts-expect-error
export const napiVersion = parseInt(process.versions.napi || '1', 10)
export const napiVersion = parseInt(process.versions.napi ?? '1', 10)

View file

@ -0,0 +1,39 @@
import test from 'ava'
import { napiVersion } from '../napi-version'
const bindings = require('../../index.node')
test('deserialize string', (t) => {
t.notThrows(() => bindings.expect_hello_world('hello world'))
})
test('deserialize object', (t) => {
if (napiVersion < 6) {
t.throws(() => {
bindings.expect_obj({})
})
} else {
t.notThrows(() =>
bindings.expect_obj({
a: 1,
b: [1, 2],
c: 'abc',
d: false,
e: null,
f: null,
g: [9, false, 'efg'],
h: '🤷',
i: 'Empty',
j: { Tuple: [27, 'hij'] },
k: { Struct: { a: 128, b: [9, 8, 7] } },
l: 'jkl',
m: [0, 1, 2, 3, 4],
o: { Value: ['z', 'y', 'x'] },
p: [1, 2, 3.5],
q: BigInt('9998881288248882845242411222333'),
r: BigInt('-3332323888900001232323022221345'),
}),
)
}
})

View file

@ -0,0 +1,26 @@
import test from 'ava'
import { napiVersion } from '../napi-version'
const bindings = require('../../index.node')
const testFunc = [
'make_num_77',
'make_num_32',
'make_str_hello',
'make_num_array',
'make_buff',
'make_obj',
'make_map',
]
if (napiVersion >= 6) {
// bigint inside
testFunc.push('make_object')
}
for (const func of testFunc) {
test(`serialize ${func} from bindings`, (t) => {
t.snapshot(bindings[func]())
})
}

View file

@ -0,0 +1,130 @@
# Snapshot report for `test_module/__test__/serde/ser.spec.ts`
The actual snapshot is saved in `ser.spec.ts.snap`.
Generated by [AVA](https://avajs.dev).
## serialize make_buff from bindings
> Snapshot 1
Buffer @Uint8Array [
fffefd
]
## serialize make_map from bindings
> Snapshot 1
{
a: 1,
b: 2,
c: 3,
}
## serialize make_num_32 from bindings
> Snapshot 1
32
## serialize make_num_77 from bindings
> Snapshot 1
77
## serialize make_num_array from bindings
> Snapshot 1
[
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
]
## serialize make_obj from bindings
> Snapshot 1
{
a: 1,
b: [
0.1,
1.1,
2.2,
3.3,
],
c: 'Hi',
}
## serialize make_object from bindings
> Snapshot 1
{
a: 1,
b: [
1,
2,
],
c: 'abc',
d: false,
e: null,
f: null,
g: [
9,
false,
'efg',
],
h: '🤷',
i: 'Empty',
j: [
27,
'hij',
],
k: {
a: 128,
b: [
9,
8,
7,
],
},
l: 'jkl',
m: [
0,
1,
2,
3,
4,
],
o: {
Value: [
'z',
'y',
'x',
],
},
p: [
1,
2,
3.5,
],
q: 9998881288248882845242411222333n,
r: -340282363588614574563373375108745990111n,
}
## serialize make_str_hello from bindings
> Snapshot 1
'Hello World'

Binary file not shown.

View file

@ -2,6 +2,8 @@
extern crate napi;
#[macro_use]
extern crate napi_derive;
#[macro_use]
extern crate serde_derive;
use napi::{CallContext, Error, JsBoolean, JsString, JsUnknown, Module, Result, Status};
@ -11,10 +13,10 @@ mod libuv;
mod napi4;
#[cfg(napi5)]
mod napi5;
#[cfg(napi4)]
mod tokio_rt;
#[cfg(napi6)]
mod napi6;
#[cfg(napi4)]
mod tokio_rt;
mod buffer;
mod class;
@ -22,6 +24,7 @@ mod either;
mod external;
mod function;
mod napi_version;
mod serde;
mod string;
mod symbol;
mod task;
@ -36,24 +39,21 @@ use libuv::read_file::uv_read_file;
use napi4::{test_threadsafe_function, test_tokio_readfile, test_tsfn_error};
#[cfg(napi5)]
use napi5::is_date::test_object_is_date;
#[cfg(napi6)]
use napi6::bigint::{
test_create_bigint_from_i64, test_create_bigint_from_u64, test_create_bigint_from_words,
test_get_bigint_i64, test_get_bigint_u64, test_get_bigint_words,
};
use napi_version::get_napi_version;
use symbol::{create_named_symbol, create_symbol_from_js_string, create_unnamed_symbol};
use task::test_spawn_thread;
#[cfg(napi4)]
use tokio_rt::{error_from_tokio_future, test_execute_tokio_readfile};
#[cfg(napi6)]
use napi6::bigint::{
test_create_bigint_from_i64,
test_create_bigint_from_u64,
test_create_bigint_from_words,
test_get_bigint_i64,
test_get_bigint_u64,
test_get_bigint_words,
};
register_module!(test_module, init);
fn init(module: &mut Module) -> Result<()> {
serde::register_serde_func(module)?;
module.create_named_method("testThrow", test_throw)?;
module.create_named_method("testThrowWithReason", test_throw_with_reason)?;
module.create_named_method("testSpawnThread", test_spawn_thread)?;

View file

@ -1,15 +1,10 @@
use std::path::Path;
use std::thread;
use napi::sys::{
napi_threadsafe_function_call_mode::napi_tsfn_blocking,
napi_threadsafe_function_release_mode::napi_tsfn_release,
};
use napi::threadsafe_function::{ThreadsafeFunction, ToJs};
use napi::{
CallContext, Env, Error, JsFunction, JsString, JsUndefined, Result, Status,
JsUnknown,
use napi::threadsafe_function::{
ThreadsafeFunction, ThreadsafeFunctionCallMode, ThreadsafeFunctionReleaseMode, ToJs,
};
use napi::{CallContext, Env, Error, JsFunction, JsString, JsUndefined, JsUnknown, Result, Status};
use tokio;
#[derive(Clone, Copy)]
@ -38,9 +33,15 @@ pub fn test_threadsafe_function(ctx: CallContext) -> Result<JsUndefined> {
thread::spawn(move || {
let output: Vec<u8> = vec![42, 1, 2, 3];
// It's okay to call a threadsafe function multiple times.
tsfn.call(Ok(output.clone()), napi_tsfn_blocking).unwrap();
tsfn.call(Ok(output.clone()), napi_tsfn_blocking).unwrap();
tsfn.release(napi_tsfn_release).unwrap();
tsfn
.call(Ok(output.clone()), ThreadsafeFunctionCallMode::Blocking)
.unwrap();
tsfn
.call(Ok(output.clone()), ThreadsafeFunctionCallMode::Blocking)
.unwrap();
tsfn
.release(ThreadsafeFunctionReleaseMode::Release)
.unwrap();
});
ctx.env.get_undefined()
@ -56,10 +57,12 @@ pub fn test_tsfn_error(ctx: CallContext) -> Result<JsUndefined> {
tsfn
.call(
Err(Error::new(Status::Unknown, "invalid".to_owned())),
napi_tsfn_blocking,
ThreadsafeFunctionCallMode::Blocking,
)
.unwrap();
tsfn.release(napi_tsfn_release).unwrap();
tsfn
.release(ThreadsafeFunctionReleaseMode::Release)
.unwrap();
});
ctx.env.get_undefined()
@ -72,7 +75,9 @@ impl ToJs for HandleBuffer {
type Output = Vec<u8>;
fn resolve(&self, env: &mut Env, output: Self::Output) -> Result<Vec<JsUnknown>> {
let value = env.create_buffer_with_data(output.to_vec())?.into_unknown()?;
let value = env
.create_buffer_with_data(output.to_vec())?
.into_unknown()?;
Ok(vec![value])
}
}
@ -96,8 +101,10 @@ pub fn test_tokio_readfile(ctx: CallContext) -> Result<JsUndefined> {
rt.block_on(async move {
let mut filepath = Path::new(path_str);
let ret = read_file_content(&mut filepath).await;
let _ = tsfn.call(ret, napi_tsfn_blocking);
tsfn.release(napi_tsfn_release).unwrap();
let _ = tsfn.call(ret, ThreadsafeFunctionCallMode::Blocking);
tsfn
.release(ThreadsafeFunctionReleaseMode::Release)
.unwrap();
});
ctx.env.get_undefined()

View file

@ -1,5 +1,5 @@
use napi::{CallContext, JsBigint, JsNumber, JsObject, Result};
use std::convert::TryFrom;
use napi::{CallContext, JsBigint, Result, JsNumber, JsObject};
#[js_function(0)]
pub fn test_create_bigint_from_i64(ctx: CallContext) -> Result<JsBigint> {
@ -13,7 +13,9 @@ pub fn test_create_bigint_from_u64(ctx: CallContext) -> Result<JsBigint> {
#[js_function(0)]
pub fn test_create_bigint_from_words(ctx: CallContext) -> Result<JsBigint> {
ctx.env.create_bigint_from_words(true, vec![u64::max_value(), u64::max_value()])
ctx
.env
.create_bigint_from_words(true, vec![u64::max_value(), u64::max_value()])
}
#[js_function(1)]
@ -32,16 +34,18 @@ pub fn test_get_bigint_u64(ctx: CallContext) -> Result<JsNumber> {
#[js_function(0)]
pub fn test_get_bigint_words(ctx: CallContext) -> Result<JsObject> {
let js_bigint = ctx.env.create_bigint_from_words(true, vec![i64::max_value() as u64, i64::max_value() as u64])?;
let mut js_bigint = ctx
.env
.create_bigint_from_words(true, vec![i64::max_value() as u64, i64::max_value() as u64])?;
let mut js_arr = ctx.env.create_array_with_length(2)?;
let words = js_bigint.get_words(true)?;
let (_signed, words) = js_bigint.get_words()?;
js_arr.set_number_indexed_property(
ctx.env.create_int64(0)?,
ctx.env.create_bigint_from_u64(words[0])?
ctx.env.create_bigint_from_u64(words[0])?,
)?;
js_arr.set_number_indexed_property(
ctx.env.create_int64(1)?,
ctx.env.create_bigint_from_u64(words[1])?
ctx.env.create_bigint_from_u64(words[1])?,
)?;
Ok(js_arr)
}

182
test_module/src/serde.rs Normal file
View file

@ -0,0 +1,182 @@
use napi::{CallContext, JsObject, JsUndefined, JsUnknown, Module, Result};
#[derive(Serialize, Debug, Deserialize)]
struct AnObject {
a: u32,
b: Vec<f64>,
c: String,
}
#[derive(Serialize, Debug, Deserialize, Eq, PartialEq)]
struct Inner;
#[derive(Serialize, Debug, Deserialize, Eq, PartialEq)]
struct Inner2(i32, bool, String);
#[derive(Serialize, Debug, Deserialize, Eq, PartialEq)]
enum TypeEnum {
Empty,
Tuple(u32, String),
Struct { a: u8, b: Vec<u8> },
Value(Vec<char>),
}
#[derive(Serialize, Debug, Deserialize, PartialEq)]
struct AnObjectTwo {
a: u32,
b: Vec<i64>,
c: String,
d: Option<bool>,
e: Option<bool>,
f: Inner,
g: Inner2,
h: char,
i: TypeEnum,
j: TypeEnum,
k: TypeEnum,
l: String,
m: Vec<u8>,
o: TypeEnum,
p: Vec<f64>,
q: u128,
r: i128,
}
macro_rules! make_test {
($name:ident, $val:expr) => {
#[js_function]
fn $name(ctx: CallContext) -> Result<JsUnknown> {
let value = $val;
ctx.env.to_js_value(&value)
}
};
}
make_test!(make_num_77, 77i32);
make_test!(make_num_32, 32u8);
make_test!(make_str_hello, "Hello World");
make_test!(make_num_array, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
make_test!(
make_obj,
AnObject {
a: 1,
b: vec![0.1f64, 1.1, 2.2, 3.3],
c: "Hi".into(),
}
);
make_test!(make_map, {
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
map
});
make_test!(make_object, {
let value = AnObjectTwo {
a: 1,
b: vec![1, 2],
c: "abc".into(),
d: Some(false),
e: None,
f: Inner,
g: Inner2(9, false, "efg".into()),
h: '🤷',
i: TypeEnum::Empty,
j: TypeEnum::Tuple(27, "hij".into()),
k: TypeEnum::Struct {
a: 128,
b: vec![9, 8, 7],
},
l: "jkl".into(),
m: vec![0, 1, 2, 3, 4],
o: TypeEnum::Value(vec!['z', 'y', 'x']),
p: vec![1., 2., 3.5],
q: 9998881288248882845242411222333,
r: -3332323888900001232323022221345,
};
value
});
const NUMBER_BYTES: &'static [u8] = &[255u8, 254, 253];
make_test!(make_buff, { serde_bytes::Bytes::new(NUMBER_BYTES) });
macro_rules! make_expect {
($name:ident, $val:expr, $val_type:ty) => {
#[js_function(1)]
fn $name(ctx: CallContext) -> Result<JsUndefined> {
let value = $val;
let arg0 = ctx.get::<JsUnknown>(0)?;
let de_serialized: $val_type = ctx.env.from_js_value(arg0)?;
assert_eq!(value, de_serialized);
ctx.env.get_undefined()
}
};
}
make_expect!(expect_hello_world, "hello world", String);
make_expect!(
expect_obj,
AnObjectTwo {
a: 1,
b: vec![1, 2],
c: "abc".into(),
d: Some(false),
e: None,
f: Inner,
g: Inner2(9, false, "efg".into()),
h: '🤷',
i: TypeEnum::Empty,
j: TypeEnum::Tuple(27, "hij".into()),
k: TypeEnum::Struct {
a: 128,
b: vec![9, 8, 7],
},
l: "jkl".into(),
m: vec![0, 1, 2, 3, 4],
o: TypeEnum::Value(vec!['z', 'y', 'x']),
p: vec![1., 2., 3.5],
q: 9998881288248882845242411222333,
r: -3332323888900001232323022221345,
},
AnObjectTwo
);
make_expect!(expect_num_array, vec![0, 1, 2, 3], Vec<i32>);
make_expect!(
expect_buffer,
serde_bytes::ByteBuf::from(vec![252u8, 251, 250]),
serde_bytes::ByteBuf
);
#[js_function(1)]
fn roundtrip_object(ctx: CallContext) -> Result<JsUnknown> {
let arg0 = ctx.get::<JsObject>(0)?;
let de_serialized: AnObjectTwo = ctx.env.from_js_value(arg0)?;
ctx.env.to_js_value(&de_serialized)
}
pub fn register_serde_func(m: &mut Module) -> Result<()> {
m.create_named_method("make_num_77", make_num_77)?;
m.create_named_method("make_num_32", make_num_32)?;
m.create_named_method("make_str_hello", make_str_hello)?;
m.create_named_method("make_num_array", make_num_array)?;
m.create_named_method("make_buff", make_buff)?;
m.create_named_method("make_obj", make_obj)?;
m.create_named_method("make_object", make_object)?;
m.create_named_method("make_map", make_map)?;
m.create_named_method("expect_hello_world", expect_hello_world)?;
m.create_named_method("expect_obj", expect_obj)?;
m.create_named_method("expect_num_array", expect_num_array)?;
m.create_named_method("expect_buffer", expect_buffer)?;
m.create_named_method("roundtrip_object", roundtrip_object)?;
Ok(())
}

View file

@ -20,25 +20,14 @@
"suppressExcessPropertyErrors": true,
"forceConsistentCasingInFileNames": true,
"preserveSymlinks": true,
"target": "ES2015",
"target": "ES2018",
"sourceMap": true,
"esModuleInterop": true,
"stripInternal": true,
"resolveJsonModule": true,
"importsNotUsedAsValues": "remove",
"outDir": "./scripts",
"lib": [
"dom",
"DOM.Iterable",
"ES5",
"ES2015",
"ES2016",
"ES2017",
"ES2018",
"ES2019",
"ES2020",
"esnext"
]
"lib": ["dom", "DOM.Iterable", "ES2019", "ES2020", "esnext"]
},
"include": ["./src"],
"exclude": ["node_modules"]

359
yarn.lock
View file

@ -10,18 +10,18 @@
"@babel/highlight" "^7.10.4"
"@babel/core@^7.7.5":
version "7.11.4"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz#4301dfdfafa01eeb97f1896c5501a3f0655d4229"
integrity sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==
version "7.11.5"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.11.5.tgz#6ad96e2f71899ea3f9b651f0a911e85205d1ff6d"
integrity sha512-fsEANVOcZHzrsV6dMVWqpSeXClq3lNbYrfFGme6DE25FQWe7pyeYpXyx9guqUnpy466JLzZ8z4uwSr2iv60V5Q==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.11.4"
"@babel/generator" "^7.11.5"
"@babel/helper-module-transforms" "^7.11.0"
"@babel/helpers" "^7.10.4"
"@babel/parser" "^7.11.4"
"@babel/parser" "^7.11.5"
"@babel/template" "^7.10.4"
"@babel/traverse" "^7.11.0"
"@babel/types" "^7.11.0"
"@babel/traverse" "^7.11.5"
"@babel/types" "^7.11.5"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.1"
@ -29,16 +29,16 @@
lodash "^4.17.19"
resolve "^1.3.2"
semver "^5.4.1"
source-map "^0.5.0"
source-map "^0.6.1"
"@babel/generator@^7.11.0", "@babel/generator@^7.11.4":
version "7.11.4"
resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz#1ec7eec00defba5d6f83e50e3ee72ae2fee482be"
integrity sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==
"@babel/generator@^7.11.5":
version "7.11.5"
resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.11.5.tgz#a5582773425a468e4ba269d9a1f701fbca6a7a82"
integrity sha512-9UqHWJ4IwRTy4l0o8gq2ef8ws8UPzvtMkVKjTLAiRmza9p9V6Z+OfuNd9fB1j5Q67F+dVJtPC2sZXI8NM9br4g==
dependencies:
"@babel/types" "^7.11.0"
"@babel/types" "^7.11.5"
jsesc "^2.5.1"
source-map "^0.5.0"
source-map "^0.6.1"
"@babel/helper-function-name@^7.10.4":
version "7.10.4"
@ -138,10 +138,10 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.4":
version "7.11.4"
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz#6fa1a118b8b0d80d0267b719213dc947e88cc0ca"
integrity sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==
"@babel/parser@^7.10.4", "@babel/parser@^7.11.5":
version "7.11.5"
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==
"@babel/template@^7.10.4":
version "7.10.4"
@ -152,25 +152,25 @@
"@babel/parser" "^7.10.4"
"@babel/types" "^7.10.4"
"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0":
version "7.11.0"
resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24"
integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==
"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5":
version "7.11.5"
resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3"
integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.11.0"
"@babel/generator" "^7.11.5"
"@babel/helper-function-name" "^7.10.4"
"@babel/helper-split-export-declaration" "^7.11.0"
"@babel/parser" "^7.11.0"
"@babel/types" "^7.11.0"
"@babel/parser" "^7.11.5"
"@babel/types" "^7.11.5"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.19"
"@babel/types@^7.10.4", "@babel/types@^7.11.0":
version "7.11.0"
resolved "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d"
integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==
"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.11.5":
version "7.11.5"
resolved "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
lodash "^4.17.19"
@ -183,6 +183,16 @@
dependencies:
arrify "^1.0.1"
"@eslint/eslintrc@^0.1.0":
version "0.1.0"
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.0.tgz#3d1f19fb797d42fb1c85458c1c73541eeb1d9e76"
integrity sha512-bfL5365QSCmH6cPeFT7Ywclj8C7LiF7sO6mUGzZhtAMV7iID1Euq6740u/SRi4C80NOnVz/CEfK8/HO+nCAPJg==
dependencies:
ajv "^6.12.4"
debug "^4.1.1"
import-fresh "^3.2.1"
strip-json-comments "^3.1.1"
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@ -206,12 +216,12 @@
resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@node-rs/helper@^0.3.0":
version "0.3.0"
resolved "https://registry.npmjs.org/@node-rs/helper/-/helper-0.3.0.tgz#6ab53f3842086f56df92f4990dda642afba84f10"
integrity sha512-1p67WcdFAtz5jVGpzpqJL2W+JKmoW4jmPD2cIJOAU4U+Fl5G9QsoFTa07ctiNosSsjYqnvgyE0KWV75YdpDqDg==
"@node-rs/helper@^0.3.1":
version "0.3.1"
resolved "https://registry.npmjs.org/@node-rs/helper/-/helper-0.3.1.tgz#605d3fafb344a4b7b664236c9219ac3e1d72361b"
integrity sha512-3X6SJOcyFRYv1mjrjtSHiziJuzAsqaz2pFD3uuLxu4qJo4TH6H0gaUb1Bdxl/VtiDy2yR+eMyBOQFCvr/G2oLA==
dependencies:
tslib "^2.0.0"
tslib "^2.0.1"
"@nodelib/fs.scandir@2.1.3":
version "2.1.3"
@ -239,51 +249,51 @@
resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
"@swc-node/core-darwin@^0.4.2":
version "0.4.2"
resolved "https://registry.npmjs.org/@swc-node/core-darwin/-/core-darwin-0.4.2.tgz#d41fff560d20e1dc0bf1d077e3ad9eebe1f83862"
integrity sha512-PKQZs5Cd1zD0D8KUz2vKGfQET7b19TcIuJ3M5fffosCLo0PV39bi6jrRiILiyP8DPGhOHysOMYkpJh0suVV2uA==
"@swc-node/core-darwin@^0.6.1":
version "0.6.1"
resolved "https://registry.npmjs.org/@swc-node/core-darwin/-/core-darwin-0.6.1.tgz#ad20762202eb25523bb6bdde81e6f6cb5e909bd9"
integrity sha512-tMWzyFhq4zPKnqq7yhUknFQWIishokFMMaqaptXq8w3wnidOhUCr83GhVggnj8r8LnUtNB8pegEj17Kl/20qjQ==
"@swc-node/core-linux-musl@^0.6.0":
version "0.6.0"
resolved "https://registry.npmjs.org/@swc-node/core-linux-musl/-/core-linux-musl-0.6.0.tgz#b657cce9fc35dddbfb84305a52546d0ece327201"
integrity sha512-gOB6PxKs26ZWt4JHIvU4Le8Sht9Ob7t7n2UF7uWwsJ6idDE89SybvZBGfi8B/AKrP2ZQPMi1wNOJABTu8O7ZUw==
"@swc-node/core-linux-musl@^0.6.1":
version "0.6.1"
resolved "https://registry.npmjs.org/@swc-node/core-linux-musl/-/core-linux-musl-0.6.1.tgz#45e2e0b695f594df944f892e9f82a2ce77266bf1"
integrity sha512-VcQ1kdeRw1D8/uMk90wHSMJmT41Tex8iytuGKBl/bVOZ5wPD9wA3Sz5ieMgt4CNiUtVITTlpyTJuQgO526W7Ug==
"@swc-node/core-linux@^0.4.2":
version "0.4.2"
resolved "https://registry.npmjs.org/@swc-node/core-linux/-/core-linux-0.4.2.tgz#e65750d1bcde9f153ec5e2b418e9b56365c94691"
integrity sha512-DOgOclLtbAOA0oJqxjOk6ziYLJ9JeTE/b9GJQm2GLB2jZgMcAPp+u1Dj/cBWEek77YErMeLyD0sYxE4E56KpvQ==
"@swc-node/core-linux@^0.6.1":
version "0.6.1"
resolved "https://registry.npmjs.org/@swc-node/core-linux/-/core-linux-0.6.1.tgz#b17ad7a8dcc1e2c17951e871cfa5c535f1e74145"
integrity sha512-oeE50kwZ8FgmP+MDFWi5aQpi4A+xUsqBQphTI4Cth7IdNqWbCq+sKU1dMn5FBFpyrp9KxXX9zrWOZYN6dtlwcg==
"@swc-node/core-win32@^0.4.2":
version "0.4.2"
resolved "https://registry.npmjs.org/@swc-node/core-win32/-/core-win32-0.4.2.tgz#26b1a2a2c33da75d5e3b2876f61dfa81188fcfc8"
integrity sha512-GopRvIP/m2uJFaEEz3IuCEKBWjZxu/mW53fWjCrib5tU/Vs3bYu2oRs7u2n6XwCDMfPw8RNNutGtbYeWQWYklw==
"@swc-node/core-win32@^0.6.1":
version "0.6.1"
resolved "https://registry.npmjs.org/@swc-node/core-win32/-/core-win32-0.6.1.tgz#7c2c09a1d713166a7d86bc4ac74fdfdcd0901314"
integrity sha512-6t8wbrbrY28nLP0rPY6nAuz6wUAZRVwkuEVt6QDrz44eo8wJkPqmZBHhYubDgdiofnxHNOveR9i9sdH2Z7xOSg==
"@swc-node/core@^0.4.2":
version "0.4.2"
resolved "https://registry.npmjs.org/@swc-node/core/-/core-0.4.2.tgz#4216cb176fc352d7df09b1cf2579274931dc5644"
integrity sha512-32YeSm2Q4YClpKIA2ZJzdZDLvLcv3nyg6pyoupy/cJjLpojGg+Laigo310wkQaCt8Y0NYOOheI/o58TV8xtgYg==
"@swc-node/core@^0.6.1":
version "0.6.1"
resolved "https://registry.npmjs.org/@swc-node/core/-/core-0.6.1.tgz#f3cf3b669f094f6b3d6f78ade54224aaa62a3362"
integrity sha512-5DXGG7u1lawiZuqv2MDgKgXNpjXu08uxg89bPU8PJATGeP+EQtJDgHwM7uF1hmRM1wsOsIy4o1t10w6NUWKCxQ==
dependencies:
"@node-rs/helper" "^0.3.0"
"@node-rs/helper" "^0.3.1"
optionalDependencies:
"@swc-node/core-darwin" "^0.4.2"
"@swc-node/core-linux" "^0.4.2"
"@swc-node/core-win32" "^0.4.2"
"@swc-node/core-darwin" "^0.6.1"
"@swc-node/core-linux" "^0.6.1"
"@swc-node/core-win32" "^0.6.1"
"@swc-node/register@^0.4.2":
version "0.4.2"
resolved "https://registry.npmjs.org/@swc-node/register/-/register-0.4.2.tgz#5d07e1c16fca102a27490d3ec5eeafcdd22a8b33"
integrity sha512-F0kD0gOWu2t8br8UZeAfrUFvab7iLs678DoVQrDseqZWSNtqF43F7upQBBKlDRO+mVOCtwdRxGanm/R0Y+aqOA==
"@swc-node/register@^0.4.5":
version "0.4.5"
resolved "https://registry.npmjs.org/@swc-node/register/-/register-0.4.5.tgz#3e80f7f901cc45d17b88a6ee626016cafd30fbe5"
integrity sha512-7wY7i19u0ISfR4vmuzPh8XDwum31kiCvQEzkZ55EjzeUVBXhNm280as81jqsGiVW3dN2mlTHfQNLB9WwOLkEnQ==
dependencies:
"@swc-node/core" "^0.4.2"
"@swc-node/sourcemap-support" "^0.1.7"
"@swc-node/core" "^0.6.1"
"@swc-node/sourcemap-support" "^0.1.8"
debug "^4.1.1"
pirates "^4.0.1"
"@swc-node/sourcemap-support@^0.1.7":
version "0.1.7"
resolved "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.1.7.tgz#2e9b94e0bb7735f4b1ce0f0a464325dd0ad25465"
integrity sha512-tC/h/JJi5WJuLbDbWt2aKFLyafUrbSnRwcpO89jmQIVtQUssbfoXGupoGrPThzCfrJyXUNNflWxl3SxIdCvPMA==
"@swc-node/sourcemap-support@^0.1.8":
version "0.1.8"
resolved "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.1.8.tgz#8cf74175ae5e3374612011e7e75c03637019db4c"
integrity sha512-AOH32yNN8UJh6Ayc+r3mnPdrjqqEjtXr9wsEiEhh3OqJWFXqkMOHC+18FYhHdTzGzhaYqUshQONjqOTC38yx7Q==
dependencies:
source-map-support "^0.5.19"
@ -299,11 +309,6 @@
resolved "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
"@types/eslint-visitor-keys@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
"@types/glob@^7.1.1":
version "7.1.3"
resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
@ -321,9 +326,9 @@
rxjs "^6.4.0"
"@types/json-schema@^7.0.3":
version "7.0.5"
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd"
integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==
version "7.0.6"
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
"@types/json5@^0.0.29":
version "0.0.29"
@ -335,10 +340,10 @@
resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*", "@types/node@^14.6.0":
version "14.6.0"
resolved "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz#7d4411bf5157339337d7cff864d9ff45f177b499"
integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==
"@types/node@*", "@types/node@^14.6.2":
version "14.6.2"
resolved "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz#264b44c5a28dfa80198fc2f7b6d3c8a054b9491f"
integrity sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@ -357,92 +362,61 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^4.0.0":
version "4.0.0"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.0.0.tgz#99349a501447fed91de18346705c0c65cf603bee"
integrity sha512-5e6q1TR7gS2P+8W2xndCu7gBh3BzmYEo70OyIdsmCmknHha/yNbz2vdevl+tP1uoaMOcrzg4gyrAijuV3DDBHA==
"@typescript-eslint/eslint-plugin@^4.0.1":
version "4.0.1"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.0.1.tgz#88bde9239e29d688315718552cf80a3490491017"
integrity sha512-pQZtXupCn11O4AwpYVUX4PDFfmIJl90ZgrEBg0CEcqlwvPiG0uY81fimr1oMFblZnpKAq6prrT9a59pj1x58rw==
dependencies:
"@typescript-eslint/experimental-utils" "4.0.0"
"@typescript-eslint/scope-manager" "4.0.0"
"@typescript-eslint/experimental-utils" "4.0.1"
"@typescript-eslint/scope-manager" "4.0.1"
debug "^4.1.1"
functional-red-black-tree "^1.0.1"
regexpp "^3.0.0"
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/experimental-utils@3.10.1":
version "3.10.1"
resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686"
integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==
"@typescript-eslint/experimental-utils@4.0.1":
version "4.0.1"
resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.0.1.tgz#7d9a3ab6821ad5274dad2186c1aa0d93afd696eb"
integrity sha512-gAqOjLiHoED79iYTt3F4uSHrYmg/GPz/zGezdB0jAdr6S6gwNiR/j7cTZ8nREKVzMVKLd9G3xbg1sV9GClW3sw==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/types" "3.10.1"
"@typescript-eslint/typescript-estree" "3.10.1"
"@typescript-eslint/scope-manager" "4.0.1"
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/typescript-estree" "4.0.1"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/experimental-utils@4.0.0":
version "4.0.0"
resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.0.0.tgz#fbec21a3b5ab59127edb6ce2e139ed378cc50eb5"
integrity sha512-hbX6zR+a/vcpFVNJYN/Nbd7gmaMosDTxHEKcvmhWeWcq/0UDifrqmCfkkodbAKL46Fn4ekSBMTyq2zlNDzcQxw==
"@typescript-eslint/parser@^4.0.1":
version "4.0.1"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.0.1.tgz#73772080db7a7a4534a35d719e006f503e664dc3"
integrity sha512-1+qLmXHNAWSQ7RB6fdSQszAiA7JTwzakj5cNYjBTUmpH2cqilxMZEIV+DRKjVZs8NzP3ALmKexB0w/ExjcK9Iw==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/scope-manager" "4.0.0"
"@typescript-eslint/types" "4.0.0"
"@typescript-eslint/typescript-estree" "4.0.0"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/parser@^3.10.1":
version "3.10.1"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467"
integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==
dependencies:
"@types/eslint-visitor-keys" "^1.0.0"
"@typescript-eslint/experimental-utils" "3.10.1"
"@typescript-eslint/types" "3.10.1"
"@typescript-eslint/typescript-estree" "3.10.1"
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/scope-manager@4.0.0":
version "4.0.0"
resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.0.0.tgz#8c9e3b3b8cdf5a1fbe671d9fad73ff67bc027ea8"
integrity sha512-9gcWUPoWo7gk/+ZQPg7L1ySRmR5HLIy3Vu6/LfhQbuzIkGm6v2CGIjpVRISoDLFRovNRDImd4aP/sa8O4yIEBg==
dependencies:
"@typescript-eslint/types" "4.0.0"
"@typescript-eslint/visitor-keys" "4.0.0"
"@typescript-eslint/types@3.10.1":
version "3.10.1"
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727"
integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==
"@typescript-eslint/types@4.0.0":
version "4.0.0"
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.0.0.tgz#ec1f9fc06b8558a1d5afa6e337182d08beece7f5"
integrity sha512-bK+c2VLzznX2fUWLK6pFDv3cXGTp7nHIuBMq1B9klA+QCsqLHOOqe5TQReAQDl7DN2RfH+neweo0oC5hYlG7Rg==
"@typescript-eslint/typescript-estree@3.10.1":
version "3.10.1"
resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853"
integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==
dependencies:
"@typescript-eslint/types" "3.10.1"
"@typescript-eslint/visitor-keys" "3.10.1"
"@typescript-eslint/scope-manager" "4.0.1"
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/typescript-estree" "4.0.1"
debug "^4.1.1"
glob "^7.1.6"
is-glob "^4.0.1"
lodash "^4.17.15"
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/typescript-estree@4.0.0":
version "4.0.0"
resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.0.0.tgz#2244c63de2f2190bc5718eb0fb3fd2c437d42097"
integrity sha512-ewFMPi2pMLDNIXGMPdf8r7El2oPSZw9PEYB0j+WcpKd7AX2ARmajGa7RUHTukllWX2bj4vWX6JLE1Oih2BMokA==
"@typescript-eslint/scope-manager@4.0.1":
version "4.0.1"
resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.0.1.tgz#24d93c3000bdfcc5a157dc4d32b742405a8631b5"
integrity sha512-u3YEXVJ8jsj7QCJk3om0Y457fy2euEOkkzxIB/LKU3MdyI+FJ2gI0M4aKEaXzwCSfNDiZ13a3lDo5DVozc+XLQ==
dependencies:
"@typescript-eslint/types" "4.0.0"
"@typescript-eslint/visitor-keys" "4.0.0"
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/visitor-keys" "4.0.1"
"@typescript-eslint/types@4.0.1":
version "4.0.1"
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.0.1.tgz#1cf72582f764931f085cb8230ff215980fe467b2"
integrity sha512-S+gD3fgbkZYW2rnbjugNMqibm9HpEjqZBZkTiI3PwbbNGWmAcxolWIUwZ0SKeG4Dy2ktpKKaI/6+HGYVH8Qrlg==
"@typescript-eslint/typescript-estree@4.0.1":
version "4.0.1"
resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.0.1.tgz#29a43c7060641ec51c902d9f50ac7c5866ec479f"
integrity sha512-zGzleORFXrRWRJAMLTB2iJD1IZbCPkg4hsI8mGdpYlKaqzvKYSEWVAYh14eauaR+qIoZVWrXgYSXqLtTlxotiw==
dependencies:
"@typescript-eslint/types" "4.0.1"
"@typescript-eslint/visitor-keys" "4.0.1"
debug "^4.1.1"
globby "^11.0.1"
is-glob "^4.0.1"
@ -450,19 +424,12 @@
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/visitor-keys@3.10.1":
version "3.10.1"
resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931"
integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==
"@typescript-eslint/visitor-keys@4.0.1":
version "4.0.1"
resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.0.1.tgz#d4e8de62775f2a6db71c7e8539633680039fdd6c"
integrity sha512-yBSqd6FjnTzbg5RUy9J+9kJEyQjTI34JdGMJz+9ttlJzLCnGkBikxw+N5n2VDcc3CesbIEJ0MnZc5uRYnrEnCw==
dependencies:
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/visitor-keys@4.0.0":
version "4.0.0"
resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.0.0.tgz#e2bbb69d98076d6a3f06abcb2048225a74362c33"
integrity sha512-sTouJbv6rjVJeTE4lpSBVYXq/u5K3gbB6LKt7ccFEZPTZB/VeQ0ssUz9q5Hx++sCqBbdF8PzrrgvEnicXAR6NQ==
dependencies:
"@typescript-eslint/types" "4.0.0"
"@typescript-eslint/types" "4.0.1"
eslint-visitor-keys "^2.0.0"
acorn-jsx@^5.2.0:
@ -493,7 +460,7 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0"
indent-string "^4.0.0"
ajv@^6.10.0, ajv@^6.10.2:
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4:
version "6.12.4"
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234"
integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==
@ -850,9 +817,9 @@ clean-yaml-object@^0.1.0:
integrity sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=
cli-boxes@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
version "2.2.1"
resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
cli-cursor@^3.1.0:
version "3.1.0"
@ -879,10 +846,10 @@ cli-width@^3.0.0:
resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
clipanion@^2.4.4:
version "2.4.4"
resolved "https://registry.npmjs.org/clipanion/-/clipanion-2.4.4.tgz#d70244c6f60feb3f4cbd509d2fcbe829fc619061"
integrity sha512-KjyCBz8xplftHjIK/nOqq/9b3hPlXbAAo/AxoITrO4yySpQ6a9QSJDAfOx9PfcRUHteeqbdNxZKSPfeFqQ7plg==
clipanion@^2.5.0:
version "2.5.0"
resolved "https://registry.npmjs.org/clipanion/-/clipanion-2.5.0.tgz#eb9c85a6b52a46979b7eb1e79534b23c44a52971"
integrity sha512-VYOMl0h/mZXQC2BWq7oBto1zY1SkPWUaJjt+cuIred1HrmrcX1I2N+LNyNoRy8Iwu9r6vUxJwS/tWLwhQW4tPw==
cliui@^6.0.0:
version "6.0.0"
@ -1351,12 +1318,13 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
eslint@^7.7.0:
version "7.7.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.7.0.tgz#18beba51411927c4b64da0a8ceadefe4030d6073"
integrity sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==
eslint@^7.8.0:
version "7.8.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.8.0.tgz#9a3e2e6e4d0a3f8c42686073c25ebf2e91443e8a"
integrity sha512-qgtVyLZqKd2ZXWnLQA4NtVbOyH56zivOAdBFWE54RFkSZjokzNrcP4Z0eVWsZ+84ByXv+jL9k/wE1ENYe8xRFw==
dependencies:
"@babel/code-frame" "^7.0.0"
"@eslint/eslintrc" "^0.1.0"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
@ -1366,7 +1334,7 @@ eslint@^7.7.0:
eslint-scope "^5.1.0"
eslint-utils "^2.1.0"
eslint-visitor-keys "^1.3.0"
espree "^7.2.0"
espree "^7.3.0"
esquery "^1.2.0"
esutils "^2.0.2"
file-entry-cache "^5.0.1"
@ -1393,7 +1361,7 @@ eslint@^7.7.0:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
espree@^7.2.0:
espree@^7.3.0:
version "7.3.0"
resolved "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348"
integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==
@ -1415,18 +1383,18 @@ esquery@^1.2.0:
estraverse "^5.1.0"
esrecurse@^4.1.0:
version "4.2.1"
resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==
version "4.3.0"
resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
dependencies:
estraverse "^4.1.0"
estraverse "^5.2.0"
estraverse@^4.1.0, estraverse@^4.1.1:
estraverse@^4.1.1:
version "4.3.0"
resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
estraverse@^5.1.0:
estraverse@^5.1.0, estraverse@^5.2.0:
version "5.2.0"
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
@ -2374,9 +2342,9 @@ md5-hex@^3.0.1:
blueimp-md5 "^2.10.0"
mem@^6.1.0:
version "6.1.0"
resolved "https://registry.npmjs.org/mem/-/mem-6.1.0.tgz#846eca0bd4708a8f04b9c3f3cd769e194ae63c5c"
integrity sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg==
version "6.1.1"
resolved "https://registry.npmjs.org/mem/-/mem-6.1.1.tgz#ea110c2ebc079eca3022e6b08c85a795e77f6318"
integrity sha512-Ci6bIfq/UgcxPTYa8dQQ5FY3BzKkT894bwXWXxC/zqs0XgMO2cT20CGkOqda7gZNkmK5VP4x89IGZ6K7hfbn3Q==
dependencies:
map-age-cleaner "^0.1.3"
mimic-fn "^3.0.0"
@ -3224,11 +3192,6 @@ source-map-support@^0.5.17, source-map-support@^0.5.19:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map@^0.5.0:
version "0.5.7"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
source-map@^0.6.0, source-map@^0.6.1:
version "0.6.1"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
@ -3376,7 +3339,7 @@ strip-final-newline@^2.0.0:
resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
strip-json-comments@^3.1.0:
strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
@ -3405,9 +3368,9 @@ supports-color@^5.3.0:
has-flag "^3.0.0"
supports-color@^7.1.0:
version "7.1.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
@ -3515,7 +3478,7 @@ tslib@^1.8.1, tslib@^1.9.0:
resolved "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
tslib@^2.0.0, tslib@^2.0.1:
tslib@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
@ -3593,9 +3556,9 @@ update-notifier@^4.1.1:
xdg-basedir "^4.0.0"
uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
version "4.4.0"
resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602"
integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==
dependencies:
punycode "^2.1.0"