Merge branch 'tsify-typescript-wasm' into 'main'
[WASM] New APIs: Enhanced JS interop and TypeScript type generation See merge request veilid/veilid!130
This commit is contained in:
commit
d6c3d8fddd
70
Cargo.lock
generated
70
Cargo.lock
generated
@ -2136,6 +2136,19 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-utils"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gloo-utils"
|
name = "gloo-utils"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -4250,7 +4263,7 @@ checksum = "ec0f696e21e10fa546b7ffb1c9672c6de8fbc7a81acf59524386d8639bf12737"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde_derive_internals",
|
"serde_derive_internals 0.26.0",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4358,6 +4371,17 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde-wasm-bindgen"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_cbor"
|
name = "serde_cbor"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
@ -4390,6 +4414,17 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive_internals"
|
||||||
|
version = "0.28.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.31",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.105"
|
version = "1.0.105"
|
||||||
@ -5347,6 +5382,32 @@ version = "0.2.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tsify"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0"
|
||||||
|
dependencies = [
|
||||||
|
"gloo-utils 0.1.7",
|
||||||
|
"serde",
|
||||||
|
"serde-wasm-bindgen",
|
||||||
|
"serde_json",
|
||||||
|
"tsify-macros",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tsify-macros"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a94b0f0954b3e59bfc2c246b4c8574390d94a4ad4ad246aaf2fb07d7dfd3b47"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde_derive_internals 0.28.0",
|
||||||
|
"syn 2.0.31",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tungstenite"
|
name = "tungstenite"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@ -5614,6 +5675,7 @@ dependencies = [
|
|||||||
"send_wrapper 0.6.0",
|
"send_wrapper 0.6.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde-big-array",
|
"serde-big-array",
|
||||||
|
"serde-wasm-bindgen",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serial_test 2.0.0",
|
"serial_test 2.0.0",
|
||||||
"shell-words",
|
"shell-words",
|
||||||
@ -5631,6 +5693,7 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"tracing-wasm",
|
"tracing-wasm",
|
||||||
"trust-dns-resolver",
|
"trust-dns-resolver",
|
||||||
|
"tsify",
|
||||||
"veilid-bugsalot",
|
"veilid-bugsalot",
|
||||||
"veilid-hashlink",
|
"veilid-hashlink",
|
||||||
"veilid-igd",
|
"veilid-igd",
|
||||||
@ -5813,15 +5876,18 @@ dependencies = [
|
|||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"gloo-utils",
|
"gloo-utils 0.2.0",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"parking_lot 0.12.1",
|
||||||
"send_wrapper 0.6.0",
|
"send_wrapper 0.6.0",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde-wasm-bindgen",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"tracing-wasm",
|
"tracing-wasm",
|
||||||
|
"tsify",
|
||||||
"veilid-core",
|
"veilid-core",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
|
@ -199,6 +199,8 @@ wasm-bindgen = "0.2.87"
|
|||||||
js-sys = "0.3.64"
|
js-sys = "0.3.64"
|
||||||
wasm-bindgen-futures = "0.4.37"
|
wasm-bindgen-futures = "0.4.37"
|
||||||
send_wrapper = { version = "0.6.0", features = ["futures"] }
|
send_wrapper = { version = "0.6.0", features = ["futures"] }
|
||||||
|
tsify = { version = "0.4.5", features = ["js"] }
|
||||||
|
serde-wasm-bindgen = "0.5.0"
|
||||||
|
|
||||||
# Network
|
# Network
|
||||||
ws_stream_wasm = "0.7.4"
|
ws_stream_wasm = "0.7.4"
|
||||||
|
@ -231,7 +231,7 @@ impl VeilidCoreContext {
|
|||||||
update_callback: UpdateCallback,
|
update_callback: UpdateCallback,
|
||||||
config_json: String,
|
config_json: String,
|
||||||
) -> VeilidAPIResult<VeilidCoreContext> {
|
) -> VeilidAPIResult<VeilidCoreContext> {
|
||||||
// Set up config from callback
|
// Set up config from json
|
||||||
trace!("setup config with json");
|
trace!("setup config with json");
|
||||||
let mut config = VeilidConfig::new();
|
let mut config = VeilidConfig::new();
|
||||||
config.setup_from_json(config_json, update_callback.clone())?;
|
config.setup_from_json(config_json, update_callback.clone())?;
|
||||||
|
@ -78,6 +78,7 @@ where
|
|||||||
macro_rules! byte_array_type {
|
macro_rules! byte_array_type {
|
||||||
($name:ident, $size:expr, $encoded_size:expr) => {
|
($name:ident, $size:expr, $encoded_size:expr) => {
|
||||||
#[derive(Clone, Copy, Hash)]
|
#[derive(Clone, Copy, Hash)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(into_wasm_abi))]
|
||||||
pub struct $name {
|
pub struct $name {
|
||||||
pub bytes: [u8; $size],
|
pub bytes: [u8; $size],
|
||||||
}
|
}
|
||||||
@ -293,11 +294,17 @@ macro_rules! byte_array_type {
|
|||||||
|
|
||||||
byte_array_type!(CryptoKey, CRYPTO_KEY_LENGTH, CRYPTO_KEY_LENGTH_ENCODED);
|
byte_array_type!(CryptoKey, CRYPTO_KEY_LENGTH, CRYPTO_KEY_LENGTH_ENCODED);
|
||||||
|
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type PublicKey = CryptoKey;
|
pub type PublicKey = CryptoKey;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type SecretKey = CryptoKey;
|
pub type SecretKey = CryptoKey;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type HashDigest = CryptoKey;
|
pub type HashDigest = CryptoKey;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type SharedSecret = CryptoKey;
|
pub type SharedSecret = CryptoKey;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type RouteId = CryptoKey;
|
pub type RouteId = CryptoKey;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type CryptoKeyDistance = CryptoKey;
|
pub type CryptoKeyDistance = CryptoKey;
|
||||||
|
|
||||||
byte_array_type!(Signature, SIGNATURE_LENGTH, SIGNATURE_LENGTH_ENCODED);
|
byte_array_type!(Signature, SIGNATURE_LENGTH, SIGNATURE_LENGTH_ENCODED);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(into_wasm_abi))]
|
||||||
pub struct CryptoTyped<K>
|
pub struct CryptoTyped<K>
|
||||||
where
|
where
|
||||||
K: Clone
|
K: Clone
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
#[serde(from = "Vec<CryptoTyped<K>>", into = "Vec<CryptoTyped<K>>")]
|
#[serde(from = "Vec<CryptoTyped<K>>", into = "Vec<CryptoTyped<K>>")]
|
||||||
|
// TODO: figure out hot to TS type this as `string`, since it's converted to string via the JSON API.
|
||||||
pub struct CryptoTypedGroup<K = PublicKey>
|
pub struct CryptoTypedGroup<K = PublicKey>
|
||||||
where
|
where
|
||||||
K: Clone
|
K: Clone
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(
|
||||||
|
target_arch = "wasm32",
|
||||||
|
derive(Tsify),
|
||||||
|
tsify(from_wasm_abi, into_wasm_abi)
|
||||||
|
)]
|
||||||
pub struct KeyPair {
|
pub struct KeyPair {
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
pub key: PublicKey,
|
pub key: PublicKey,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
pub secret: SecretKey,
|
pub secret: SecretKey,
|
||||||
}
|
}
|
||||||
|
from_impl_to_jsvalue!(KeyPair);
|
||||||
|
|
||||||
impl KeyPair {
|
impl KeyPair {
|
||||||
pub fn new(key: PublicKey, secret: SecretKey) -> Self {
|
pub fn new(key: PublicKey, secret: SecretKey) -> Self {
|
||||||
|
@ -6,6 +6,7 @@ use core::fmt;
|
|||||||
use core::hash::Hash;
|
use core::hash::Hash;
|
||||||
|
|
||||||
/// Cryptography version fourcc code
|
/// Cryptography version fourcc code
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type CryptoKind = FourCC;
|
pub type CryptoKind = FourCC;
|
||||||
|
|
||||||
/// Sort best crypto kinds first
|
/// Sort best crypto kinds first
|
||||||
@ -51,14 +52,24 @@ pub use crypto_typed::*;
|
|||||||
pub use crypto_typed_group::*;
|
pub use crypto_typed_group::*;
|
||||||
pub use keypair::*;
|
pub use keypair::*;
|
||||||
|
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedKey = CryptoTyped<PublicKey>;
|
pub type TypedKey = CryptoTyped<PublicKey>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedSecret = CryptoTyped<SecretKey>;
|
pub type TypedSecret = CryptoTyped<SecretKey>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedKeyPair = CryptoTyped<KeyPair>;
|
pub type TypedKeyPair = CryptoTyped<KeyPair>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedSignature = CryptoTyped<Signature>;
|
pub type TypedSignature = CryptoTyped<Signature>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedSharedSecret = CryptoTyped<SharedSecret>;
|
pub type TypedSharedSecret = CryptoTyped<SharedSecret>;
|
||||||
|
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedKeyGroup = CryptoTypedGroup<PublicKey>;
|
pub type TypedKeyGroup = CryptoTypedGroup<PublicKey>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedSecretGroup = CryptoTypedGroup<SecretKey>;
|
pub type TypedSecretGroup = CryptoTypedGroup<SecretKey>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedKeyPairGroup = CryptoTypedGroup<KeyPair>;
|
pub type TypedKeyPairGroup = CryptoTypedGroup<KeyPair>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedSignatureGroup = CryptoTypedGroup<Signature>;
|
pub type TypedSignatureGroup = CryptoTypedGroup<Signature>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TypedSharedSecretGroup = CryptoTypedGroup<SharedSecret>;
|
pub type TypedSharedSecretGroup = CryptoTypedGroup<SharedSecret>;
|
||||||
|
@ -56,6 +56,7 @@ mod table_store;
|
|||||||
mod veilid_api;
|
mod veilid_api;
|
||||||
mod veilid_config;
|
mod veilid_config;
|
||||||
mod veilid_layer_filter;
|
mod veilid_layer_filter;
|
||||||
|
mod wasm_helpers;
|
||||||
|
|
||||||
pub use self::api_tracing_layer::ApiTracingLayer;
|
pub use self::api_tracing_layer::ApiTracingLayer;
|
||||||
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
|
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
|
||||||
@ -127,3 +128,4 @@ use stop_token::*;
|
|||||||
use thiserror::Error as ThisError;
|
use thiserror::Error as ThisError;
|
||||||
use tracing::*;
|
use tracing::*;
|
||||||
use veilid_tools::*;
|
use veilid_tools::*;
|
||||||
|
use wasm_helpers::*;
|
||||||
|
2
veilid-core/src/network_manager/wasm/.cargo/config.toml
Normal file
2
veilid-core/src/network_manager/wasm/.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[build]
|
||||||
|
target = "wasm32-unknown-unknown"
|
@ -107,6 +107,7 @@ macro_rules! apibail_already_initialized {
|
|||||||
#[derive(
|
#[derive(
|
||||||
ThisError, Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize, JsonSchema,
|
ThisError, Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(into_wasm_abi))]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
pub enum VeilidAPIError {
|
pub enum VeilidAPIError {
|
||||||
#[error("Not initialized")]
|
#[error("Not initialized")]
|
||||||
@ -145,6 +146,7 @@ pub enum VeilidAPIError {
|
|||||||
#[error("Generic: {message}")]
|
#[error("Generic: {message}")]
|
||||||
Generic { message: String },
|
Generic { message: String },
|
||||||
}
|
}
|
||||||
|
from_impl_to_jsvalue!(VeilidAPIError);
|
||||||
|
|
||||||
impl VeilidAPIError {
|
impl VeilidAPIError {
|
||||||
pub fn not_initialized() -> Self {
|
pub fn not_initialized() -> Self {
|
||||||
@ -213,6 +215,7 @@ impl VeilidAPIError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type VeilidAPIResult<T> = Result<T, VeilidAPIError>;
|
pub type VeilidAPIResult<T> = Result<T, VeilidAPIError>;
|
||||||
|
|
||||||
impl From<std::io::Error> for VeilidAPIError {
|
impl From<std::io::Error> for VeilidAPIError {
|
||||||
|
@ -8,11 +8,13 @@ use super::*;
|
|||||||
#[derive(
|
#[derive(
|
||||||
Clone, Default, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, Serialize, Deserialize, JsonSchema,
|
Clone, Default, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
#[repr(C, align(8))]
|
#[repr(C, align(8))]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct AlignedU64(
|
pub struct AlignedU64(
|
||||||
#[serde(with = "as_human_string")]
|
#[serde(with = "as_human_string")]
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
u64,
|
u64,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -117,13 +119,17 @@ impl AlignedU64 {
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// Microseconds since epoch
|
/// Microseconds since epoch
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type Timestamp = AlignedU64;
|
pub type Timestamp = AlignedU64;
|
||||||
pub fn get_aligned_timestamp() -> Timestamp {
|
pub fn get_aligned_timestamp() -> Timestamp {
|
||||||
get_timestamp().into()
|
get_timestamp().into()
|
||||||
}
|
}
|
||||||
/// Microseconds duration
|
/// Microseconds duration
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type TimestampDuration = AlignedU64;
|
pub type TimestampDuration = AlignedU64;
|
||||||
/// Request/Response matching id
|
/// Request/Response matching id
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type OperationId = AlignedU64;
|
pub type OperationId = AlignedU64;
|
||||||
/// Number of bytes
|
/// Number of bytes
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type ByteCount = AlignedU64;
|
pub type ByteCount = AlignedU64;
|
||||||
|
@ -2,13 +2,16 @@ use super::*;
|
|||||||
|
|
||||||
/// Direct statement blob passed to hosting application for processing
|
/// Direct statement blob passed to hosting application for processing
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidAppMessage {
|
pub struct VeilidAppMessage {
|
||||||
#[serde(with = "as_human_opt_string")]
|
#[serde(with = "as_human_opt_string")]
|
||||||
#[schemars(with = "Option<String>")]
|
#[schemars(with = "Option<String>")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional, type = "string"))]
|
||||||
sender: Option<TypedKey>,
|
sender: Option<TypedKey>,
|
||||||
|
|
||||||
#[serde(with = "as_human_base64")]
|
#[serde(with = "as_human_base64")]
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
message: Vec<u8>,
|
message: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,9 +33,11 @@ impl VeilidAppMessage {
|
|||||||
|
|
||||||
/// Direct question blob passed to hosting application for processing to send an eventual AppReply
|
/// Direct question blob passed to hosting application for processing to send an eventual AppReply
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidAppCall {
|
pub struct VeilidAppCall {
|
||||||
#[serde(with = "as_human_opt_string")]
|
#[serde(with = "as_human_opt_string")]
|
||||||
#[schemars(with = "Option<String>")]
|
#[schemars(with = "Option<String>")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
sender: Option<TypedKey>,
|
sender: Option<TypedKey>,
|
||||||
|
|
||||||
#[serde(with = "as_human_base64")]
|
#[serde(with = "as_human_base64")]
|
||||||
|
@ -2,20 +2,29 @@ use super::*;
|
|||||||
|
|
||||||
/// DHT Record Descriptor
|
/// DHT Record Descriptor
|
||||||
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(
|
||||||
|
target_arch = "wasm32",
|
||||||
|
derive(Tsify),
|
||||||
|
tsify(from_wasm_abi, into_wasm_abi)
|
||||||
|
)]
|
||||||
pub struct DHTRecordDescriptor {
|
pub struct DHTRecordDescriptor {
|
||||||
/// DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ]
|
/// DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ]
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
key: TypedKey,
|
key: TypedKey,
|
||||||
/// The public key of the owner
|
/// The public key of the owner
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
owner: PublicKey,
|
owner: PublicKey,
|
||||||
/// If this key is being created: Some(the secret key of the owner)
|
/// If this key is being created: Some(the secret key of the owner)
|
||||||
/// If this key is just being opened: None
|
/// If this key is just being opened: None
|
||||||
#[schemars(with = "Option<String>")]
|
#[schemars(with = "Option<String>")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional, type = "string"))]
|
||||||
owner_secret: Option<SecretKey>,
|
owner_secret: Option<SecretKey>,
|
||||||
/// The schema in use associated with the key
|
/// The schema in use associated with the key
|
||||||
schema: DHTSchema,
|
schema: DHTSchema,
|
||||||
}
|
}
|
||||||
|
from_impl_to_jsvalue!(DHTRecordDescriptor);
|
||||||
|
|
||||||
impl DHTRecordDescriptor {
|
impl DHTRecordDescriptor {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
@ -11,6 +11,8 @@ pub use value_data::*;
|
|||||||
pub use value_subkey_range_set::*;
|
pub use value_subkey_range_set::*;
|
||||||
|
|
||||||
/// Value subkey
|
/// Value subkey
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type ValueSubkey = u32;
|
pub type ValueSubkey = u32;
|
||||||
/// Value sequence number
|
/// Value sequence number
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type ValueSeqNum = u32;
|
pub type ValueSeqNum = u32;
|
||||||
|
@ -2,6 +2,7 @@ use super::*;
|
|||||||
|
|
||||||
/// Default DHT Schema (DFLT)
|
/// Default DHT Schema (DFLT)
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct DHTSchemaDFLT {
|
pub struct DHTSchemaDFLT {
|
||||||
/// Owner subkey count
|
/// Owner subkey count
|
||||||
pub o_cnt: u16,
|
pub o_cnt: u16,
|
||||||
|
@ -9,6 +9,7 @@ pub use smpl::*;
|
|||||||
/// Enum over all the supported DHT Schemas
|
/// Enum over all the supported DHT Schemas
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, JsonSchema)]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi))]
|
||||||
pub enum DHTSchema {
|
pub enum DHTSchema {
|
||||||
DFLT(DHTSchemaDFLT),
|
DFLT(DHTSchemaDFLT),
|
||||||
SMPL(DHTSchemaSMPL),
|
SMPL(DHTSchemaSMPL),
|
||||||
|
@ -2,9 +2,11 @@ use super::*;
|
|||||||
|
|
||||||
/// Simple DHT Schema (SMPL) Member
|
/// Simple DHT Schema (SMPL) Member
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct DHTSchemaSMPLMember {
|
pub struct DHTSchemaSMPLMember {
|
||||||
/// Member key
|
/// Member key
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
pub m_key: PublicKey,
|
pub m_key: PublicKey,
|
||||||
/// Member subkey count
|
/// Member subkey count
|
||||||
pub m_cnt: u16,
|
pub m_cnt: u16,
|
||||||
@ -12,6 +14,7 @@ pub struct DHTSchemaSMPLMember {
|
|||||||
|
|
||||||
/// Simple DHT Schema (SMPL)
|
/// Simple DHT Schema (SMPL)
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct DHTSchemaSMPL {
|
pub struct DHTSchemaSMPL {
|
||||||
/// Owner subkey count
|
/// Owner subkey count
|
||||||
pub o_cnt: u16,
|
pub o_cnt: u16,
|
||||||
|
@ -2,6 +2,7 @@ use super::*;
|
|||||||
use veilid_api::VeilidAPIResult;
|
use veilid_api::VeilidAPIResult;
|
||||||
|
|
||||||
#[derive(Clone, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(into_wasm_abi))]
|
||||||
pub struct ValueData {
|
pub struct ValueData {
|
||||||
/// An increasing sequence number to time-order the DHT record changes
|
/// An increasing sequence number to time-order the DHT record changes
|
||||||
seq: ValueSeqNum,
|
seq: ValueSeqNum,
|
||||||
@ -9,12 +10,16 @@ pub struct ValueData {
|
|||||||
/// The contents of a DHT Record
|
/// The contents of a DHT Record
|
||||||
#[serde(with = "as_human_base64")]
|
#[serde(with = "as_human_base64")]
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
|
||||||
/// The public identity key of the writer of the data
|
/// The public identity key of the writer of the data
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
writer: PublicKey,
|
writer: PublicKey,
|
||||||
}
|
}
|
||||||
|
from_impl_to_jsvalue!(ValueData);
|
||||||
|
|
||||||
impl ValueData {
|
impl ValueData {
|
||||||
pub const MAX_LEN: usize = 32768;
|
pub const MAX_LEN: usize = 32768;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ use super::*;
|
|||||||
#[derive(
|
#[derive(
|
||||||
Copy, Default, Clone, Hash, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, JsonSchema,
|
Copy, Default, Clone, Hash, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
#[serde(try_from = "String")]
|
#[serde(try_from = "String")]
|
||||||
#[serde(into = "String")]
|
#[serde(into = "String")]
|
||||||
pub struct FourCC(pub [u8; 4]);
|
pub struct FourCC(pub [u8; 4]);
|
||||||
|
@ -4,6 +4,7 @@ use super::*;
|
|||||||
#[derive(
|
#[derive(
|
||||||
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi, namespace))]
|
||||||
pub enum Sequencing {
|
pub enum Sequencing {
|
||||||
NoPreference = 0,
|
NoPreference = 0,
|
||||||
PreferOrdered = 1,
|
PreferOrdered = 1,
|
||||||
@ -20,6 +21,7 @@ impl Default for Sequencing {
|
|||||||
#[derive(
|
#[derive(
|
||||||
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi, namespace))]
|
||||||
pub enum Stability {
|
pub enum Stability {
|
||||||
LowLatency = 0,
|
LowLatency = 0,
|
||||||
Reliable = 1,
|
Reliable = 1,
|
||||||
@ -35,6 +37,7 @@ impl Default for Stability {
|
|||||||
#[derive(
|
#[derive(
|
||||||
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi, namespace))]
|
||||||
pub enum SafetySelection {
|
pub enum SafetySelection {
|
||||||
/// Don't use a safety route, only specify the sequencing preference
|
/// Don't use a safety route, only specify the sequencing preference
|
||||||
Unsafe(Sequencing),
|
Unsafe(Sequencing),
|
||||||
@ -61,9 +64,11 @@ impl Default for SafetySelection {
|
|||||||
#[derive(
|
#[derive(
|
||||||
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct SafetySpec {
|
pub struct SafetySpec {
|
||||||
/// preferred safety route set id if it still exists
|
/// preferred safety route set id if it still exists
|
||||||
#[schemars(with = "Option<String>")]
|
#[schemars(with = "Option<String>")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional, type = "string"))]
|
||||||
pub preferred_route: Option<RouteId>,
|
pub preferred_route: Option<RouteId>,
|
||||||
/// must be greater than 0
|
/// must be greater than 0
|
||||||
pub hop_count: usize,
|
pub hop_count: usize,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct LatencyStats {
|
pub struct LatencyStats {
|
||||||
pub fastest: TimestampDuration, // fastest latency in the ROLLING_LATENCIES_SIZE last latencies
|
pub fastest: TimestampDuration, // fastest latency in the ROLLING_LATENCIES_SIZE last latencies
|
||||||
pub average: TimestampDuration, // average latency over the ROLLING_LATENCIES_SIZE last latencies
|
pub average: TimestampDuration, // average latency over the ROLLING_LATENCIES_SIZE last latencies
|
||||||
@ -8,6 +9,7 @@ pub struct LatencyStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct TransferStats {
|
pub struct TransferStats {
|
||||||
pub total: ByteCount, // total amount transferred ever
|
pub total: ByteCount, // total amount transferred ever
|
||||||
pub maximum: ByteCount, // maximum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
pub maximum: ByteCount, // maximum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||||
@ -16,12 +18,14 @@ pub struct TransferStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct TransferStatsDownUp {
|
pub struct TransferStatsDownUp {
|
||||||
pub down: TransferStats,
|
pub down: TransferStats,
|
||||||
pub up: TransferStats,
|
pub up: TransferStats,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct RPCStats {
|
pub struct RPCStats {
|
||||||
pub messages_sent: u32, // number of rpcs that have been sent in the total_time range
|
pub messages_sent: u32, // number of rpcs that have been sent in the total_time range
|
||||||
pub messages_rcvd: u32, // number of rpcs that have been received in the total_time range
|
pub messages_rcvd: u32, // number of rpcs that have been received in the total_time range
|
||||||
@ -34,6 +38,7 @@ pub struct RPCStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct PeerStats {
|
pub struct PeerStats {
|
||||||
pub time_added: Timestamp, // when the peer was added to the routing table
|
pub time_added: Timestamp, // when the peer was added to the routing table
|
||||||
pub rpc_stats: RPCStats, // information about RPCs
|
pub rpc_stats: RPCStats, // information about RPCs
|
||||||
|
@ -4,6 +4,7 @@ use super::*;
|
|||||||
#[derive(
|
#[derive(
|
||||||
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Serialize, Deserialize, JsonSchema,
|
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Serialize, Deserialize, JsonSchema,
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(namespace))]
|
||||||
pub enum VeilidLogLevel {
|
pub enum VeilidLogLevel {
|
||||||
Error = 1,
|
Error = 1,
|
||||||
Warn = 2,
|
Warn = 2,
|
||||||
@ -80,8 +81,10 @@ impl fmt::Display for VeilidLogLevel {
|
|||||||
}
|
}
|
||||||
/// A VeilidCore log message with optional backtrace
|
/// A VeilidCore log message with optional backtrace
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidLog {
|
pub struct VeilidLog {
|
||||||
pub log_level: VeilidLogLevel,
|
pub log_level: VeilidLogLevel,
|
||||||
pub message: String,
|
pub message: String,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub backtrace: Option<String>,
|
pub backtrace: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,11 @@ use super::*;
|
|||||||
|
|
||||||
/// Attachment abstraction for network 'signal strength'
|
/// Attachment abstraction for network 'signal strength'
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(
|
||||||
|
target_arch = "wasm32",
|
||||||
|
derive(Tsify),
|
||||||
|
tsify(namespace, from_wasm_abi, into_wasm_abi)
|
||||||
|
)]
|
||||||
pub enum AttachmentState {
|
pub enum AttachmentState {
|
||||||
Detached = 0,
|
Detached = 0,
|
||||||
Attaching = 1,
|
Attaching = 1,
|
||||||
@ -48,6 +53,7 @@ impl TryFrom<String> for AttachmentState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidStateAttachment {
|
pub struct VeilidStateAttachment {
|
||||||
pub state: AttachmentState,
|
pub state: AttachmentState,
|
||||||
pub public_internet_ready: bool,
|
pub public_internet_ready: bool,
|
||||||
@ -55,14 +61,17 @@ pub struct VeilidStateAttachment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct PeerTableData {
|
pub struct PeerTableData {
|
||||||
#[schemars(with = "Vec<String>")]
|
#[schemars(with = "Vec<String>")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string[]"))]
|
||||||
pub node_ids: Vec<TypedKey>,
|
pub node_ids: Vec<TypedKey>,
|
||||||
pub peer_address: String,
|
pub peer_address: String,
|
||||||
pub peer_stats: PeerStats,
|
pub peer_stats: PeerStats,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidStateNetwork {
|
pub struct VeilidStateNetwork {
|
||||||
pub started: bool,
|
pub started: bool,
|
||||||
pub bps_down: ByteCount,
|
pub bps_down: ByteCount,
|
||||||
@ -71,21 +80,27 @@ pub struct VeilidStateNetwork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidRouteChange {
|
pub struct VeilidRouteChange {
|
||||||
#[schemars(with = "Vec<String>")]
|
#[schemars(with = "Vec<String>")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
pub dead_routes: Vec<RouteId>,
|
pub dead_routes: Vec<RouteId>,
|
||||||
#[schemars(with = "Vec<String>")]
|
#[schemars(with = "Vec<String>")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
pub dead_remote_routes: Vec<RouteId>,
|
pub dead_remote_routes: Vec<RouteId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidStateConfig {
|
pub struct VeilidStateConfig {
|
||||||
pub config: VeilidConfigInner,
|
pub config: VeilidConfigInner,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidValueChange {
|
pub struct VeilidValueChange {
|
||||||
#[schemars(with = "String")]
|
#[schemars(with = "String")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
pub key: TypedKey,
|
pub key: TypedKey,
|
||||||
pub subkeys: Vec<ValueSubkey>,
|
pub subkeys: Vec<ValueSubkey>,
|
||||||
pub count: u32,
|
pub count: u32,
|
||||||
@ -93,6 +108,7 @@ pub struct VeilidValueChange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(into_wasm_abi))]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
pub enum VeilidUpdate {
|
pub enum VeilidUpdate {
|
||||||
Log(VeilidLog),
|
Log(VeilidLog),
|
||||||
@ -105,10 +121,13 @@ pub enum VeilidUpdate {
|
|||||||
ValueChange(VeilidValueChange),
|
ValueChange(VeilidValueChange),
|
||||||
Shutdown,
|
Shutdown,
|
||||||
}
|
}
|
||||||
|
from_impl_to_jsvalue!(VeilidUpdate);
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(into_wasm_abi))]
|
||||||
pub struct VeilidState {
|
pub struct VeilidState {
|
||||||
pub attachment: VeilidStateAttachment,
|
pub attachment: VeilidStateAttachment,
|
||||||
pub network: VeilidStateNetwork,
|
pub network: VeilidStateNetwork,
|
||||||
pub config: VeilidStateConfig,
|
pub config: VeilidStateConfig,
|
||||||
}
|
}
|
||||||
|
from_impl_to_jsvalue!(VeilidState);
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type ConfigCallbackReturn = VeilidAPIResult<Box<dyn core::any::Any + Send>>;
|
pub type ConfigCallbackReturn = VeilidAPIResult<Box<dyn core::any::Any + Send>>;
|
||||||
|
#[cfg_attr(target_arch = "wasm32", declare)]
|
||||||
pub type ConfigCallback = Arc<dyn Fn(String) -> ConfigCallbackReturn + Send + Sync>;
|
pub type ConfigCallback = Arc<dyn Fn(String) -> ConfigCallbackReturn + Send + Sync>;
|
||||||
|
|
||||||
/// Enable and configure HTTPS access to the Veilid node
|
/// Enable and configure HTTPS access to the Veilid node
|
||||||
@ -15,10 +17,12 @@ pub type ConfigCallback = Arc<dyn Fn(String) -> ConfigCallbackReturn + Send + Sy
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigHTTPS {
|
pub struct VeilidConfigHTTPS {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub url: Option<String>, // Fixed URL is not optional for TLS-based protocols and is dynamically validated
|
pub url: Option<String>, // Fixed URL is not optional for TLS-based protocols and is dynamically validated
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,10 +37,12 @@ pub struct VeilidConfigHTTPS {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigHTTP {
|
pub struct VeilidConfigHTTP {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub url: Option<String>,
|
pub url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +53,7 @@ pub struct VeilidConfigHTTP {
|
|||||||
/// To be implemented...
|
/// To be implemented...
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigApplication {
|
pub struct VeilidConfigApplication {
|
||||||
pub https: VeilidConfigHTTPS,
|
pub https: VeilidConfigHTTPS,
|
||||||
pub http: VeilidConfigHTTP,
|
pub http: VeilidConfigHTTP,
|
||||||
@ -63,10 +70,12 @@ pub struct VeilidConfigApplication {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigUDP {
|
pub struct VeilidConfigUDP {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub socket_pool_size: u32,
|
pub socket_pool_size: u32,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub public_address: Option<String>,
|
pub public_address: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,11 +90,13 @@ pub struct VeilidConfigUDP {
|
|||||||
/// public_address: ''
|
/// public_address: ''
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigTCP {
|
pub struct VeilidConfigTCP {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
pub listen: bool,
|
pub listen: bool,
|
||||||
pub max_connections: u32,
|
pub max_connections: u32,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub public_address: Option<String>,
|
pub public_address: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +112,7 @@ pub struct VeilidConfigTCP {
|
|||||||
/// url: 'ws://localhost:5150/ws'
|
/// url: 'ws://localhost:5150/ws'
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
|
|
||||||
pub struct VeilidConfigWS {
|
pub struct VeilidConfigWS {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
@ -108,6 +120,7 @@ pub struct VeilidConfigWS {
|
|||||||
pub max_connections: u32,
|
pub max_connections: u32,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub url: Option<String>,
|
pub url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +136,7 @@ pub struct VeilidConfigWS {
|
|||||||
/// url: ''
|
/// url: ''
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
|
|
||||||
pub struct VeilidConfigWSS {
|
pub struct VeilidConfigWSS {
|
||||||
pub connect: bool,
|
pub connect: bool,
|
||||||
@ -130,6 +144,7 @@ pub struct VeilidConfigWSS {
|
|||||||
pub max_connections: u32,
|
pub max_connections: u32,
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub url: Option<String>, // Fixed URL is not optional for TLS-based protocols and is dynamically validated
|
pub url: Option<String>, // Fixed URL is not optional for TLS-based protocols and is dynamically validated
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +156,7 @@ pub struct VeilidConfigWSS {
|
|||||||
/// sort out which protocol is used for each peer connection.
|
/// sort out which protocol is used for each peer connection.
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
|
|
||||||
pub struct VeilidConfigProtocol {
|
pub struct VeilidConfigProtocol {
|
||||||
pub udp: VeilidConfigUDP,
|
pub udp: VeilidConfigUDP,
|
||||||
@ -158,6 +174,7 @@ pub struct VeilidConfigProtocol {
|
|||||||
/// connection_initial_timeout_ms: 2000
|
/// connection_initial_timeout_ms: 2000
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigTLS {
|
pub struct VeilidConfigTLS {
|
||||||
pub certificate_path: String,
|
pub certificate_path: String,
|
||||||
pub private_key_path: String,
|
pub private_key_path: String,
|
||||||
@ -167,6 +184,7 @@ pub struct VeilidConfigTLS {
|
|||||||
/// Configure the Distributed Hash Table (DHT)
|
/// Configure the Distributed Hash Table (DHT)
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigDHT {
|
pub struct VeilidConfigDHT {
|
||||||
pub max_find_node_count: u32,
|
pub max_find_node_count: u32,
|
||||||
pub resolve_node_timeout_ms: u32,
|
pub resolve_node_timeout_ms: u32,
|
||||||
@ -192,10 +210,13 @@ pub struct VeilidConfigDHT {
|
|||||||
/// Configure RPC
|
/// Configure RPC
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigRPC {
|
pub struct VeilidConfigRPC {
|
||||||
pub concurrency: u32,
|
pub concurrency: u32,
|
||||||
pub queue_size: u32,
|
pub queue_size: u32,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub max_timestamp_behind_ms: Option<u32>,
|
pub max_timestamp_behind_ms: Option<u32>,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub max_timestamp_ahead_ms: Option<u32>,
|
pub max_timestamp_ahead_ms: Option<u32>,
|
||||||
pub timeout_ms: u32,
|
pub timeout_ms: u32,
|
||||||
pub max_route_hop_count: u8,
|
pub max_route_hop_count: u8,
|
||||||
@ -205,6 +226,7 @@ pub struct VeilidConfigRPC {
|
|||||||
/// Configure the network routing table
|
/// Configure the network routing table
|
||||||
///
|
///
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigRoutingTable {
|
pub struct VeilidConfigRoutingTable {
|
||||||
#[schemars(with = "Vec<String>")]
|
#[schemars(with = "Vec<String>")]
|
||||||
pub node_id: TypedKeyGroup,
|
pub node_id: TypedKeyGroup,
|
||||||
@ -221,6 +243,7 @@ pub struct VeilidConfigRoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigNetwork {
|
pub struct VeilidConfigNetwork {
|
||||||
pub connection_initial_timeout_ms: u32,
|
pub connection_initial_timeout_ms: u32,
|
||||||
pub connection_inactivity_timeout_ms: u32,
|
pub connection_inactivity_timeout_ms: u32,
|
||||||
@ -231,6 +254,7 @@ pub struct VeilidConfigNetwork {
|
|||||||
pub client_whitelist_timeout_ms: u32,
|
pub client_whitelist_timeout_ms: u32,
|
||||||
pub reverse_connection_receipt_time_ms: u32,
|
pub reverse_connection_receipt_time_ms: u32,
|
||||||
pub hole_punch_receipt_time_ms: u32,
|
pub hole_punch_receipt_time_ms: u32,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub network_key_password: Option<String>,
|
pub network_key_password: Option<String>,
|
||||||
pub routing_table: VeilidConfigRoutingTable,
|
pub routing_table: VeilidConfigRoutingTable,
|
||||||
pub rpc: VeilidConfigRPC,
|
pub rpc: VeilidConfigRPC,
|
||||||
@ -244,33 +268,40 @@ pub struct VeilidConfigNetwork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigTableStore {
|
pub struct VeilidConfigTableStore {
|
||||||
pub directory: String,
|
pub directory: String,
|
||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigBlockStore {
|
pub struct VeilidConfigBlockStore {
|
||||||
pub directory: String,
|
pub directory: String,
|
||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigProtectedStore {
|
pub struct VeilidConfigProtectedStore {
|
||||||
pub allow_insecure_fallback: bool,
|
pub allow_insecure_fallback: bool,
|
||||||
pub always_use_insecure_storage: bool,
|
pub always_use_insecure_storage: bool,
|
||||||
pub directory: String,
|
pub directory: String,
|
||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
pub device_encryption_key_password: String,
|
pub device_encryption_key_password: String,
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(optional))]
|
||||||
pub new_device_encryption_key_password: Option<String>,
|
pub new_device_encryption_key_password: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigCapabilities {
|
pub struct VeilidConfigCapabilities {
|
||||||
pub disable: Vec<FourCC>,
|
pub disable: Vec<FourCC>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(namespace, from_wasm_abi))]
|
||||||
pub enum VeilidConfigLogLevel {
|
pub enum VeilidConfigLogLevel {
|
||||||
Off,
|
Off,
|
||||||
Error,
|
Error,
|
||||||
@ -358,6 +389,7 @@ impl fmt::Display for VeilidConfigLogLevel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidConfigInner {
|
pub struct VeilidConfigInner {
|
||||||
pub program_name: String,
|
pub program_name: String,
|
||||||
pub namespace: String,
|
pub namespace: String,
|
||||||
|
21
veilid-core/src/wasm_helpers.rs
Normal file
21
veilid-core/src/wasm_helpers.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_arch = "wasm32")] {
|
||||||
|
pub use tsify::*;
|
||||||
|
pub use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
macro_rules! from_impl_to_jsvalue {
|
||||||
|
($name: ident) => {
|
||||||
|
impl From<$name> for JsValue {
|
||||||
|
fn from(value: $name) -> Self {
|
||||||
|
serde_wasm_bindgen::to_value(&value).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
macro_rules! from_impl_to_jsvalue {
|
||||||
|
($name: ident) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) use from_impl_to_jsvalue;
|
2
veilid-wasm/.cargo/config.toml
Normal file
2
veilid-wasm/.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[build]
|
||||||
|
target = "wasm32-unknown-unknown"
|
@ -34,6 +34,9 @@ send_wrapper = "^0"
|
|||||||
futures-util = { version = "^0" }
|
futures-util = { version = "^0" }
|
||||||
data-encoding = { version = "^2" }
|
data-encoding = { version = "^2" }
|
||||||
gloo-utils = { version = "^0", features = ["serde"] }
|
gloo-utils = { version = "^0", features = ["serde"] }
|
||||||
|
tsify = { version = "0.4.5", features = ["js"] }
|
||||||
|
serde-wasm-bindgen = "0.5.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasm-bindgen-test = "^0"
|
wasm-bindgen-test = "^0"
|
||||||
|
parking_lot = "0.12.1"
|
||||||
|
6
veilid-wasm/README.md
Normal file
6
veilid-wasm/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# veilid-wasm
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- [`wasm_bindgen`](https://rustwasm.github.io/wasm-bindgen/) is used to generate interop code between JavaScript and Rust, as well as basic TypeScript types.
|
||||||
|
- [`tsify`](https://github.com/madonoharu/tsify) is used to export TypeScript types along-side [`wasm_bindgen`](https://rustwasm.github.io/wasm-bindgen/) and [`serde_wasm_bindgen`](https://github.com/cloudflare/serde-wasm-bindgen), and enables serialization/deserialization.
|
@ -19,11 +19,20 @@ use serde::*;
|
|||||||
use tracing_subscriber::prelude::*;
|
use tracing_subscriber::prelude::*;
|
||||||
use tracing_subscriber::*;
|
use tracing_subscriber::*;
|
||||||
use tracing_wasm::{WASMLayerConfigBuilder, *};
|
use tracing_wasm::{WASMLayerConfigBuilder, *};
|
||||||
|
use tsify::*;
|
||||||
use veilid_core::tools::*;
|
use veilid_core::tools::*;
|
||||||
use veilid_core::*;
|
use veilid_core::*;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use wasm_bindgen_futures::*;
|
use wasm_bindgen_futures::*;
|
||||||
|
|
||||||
|
pub mod veilid_client_js;
|
||||||
|
pub mod veilid_crypto_js;
|
||||||
|
pub mod veilid_routing_context_js;
|
||||||
|
pub mod veilid_table_db_js;
|
||||||
|
|
||||||
|
mod wasm_helpers;
|
||||||
|
use wasm_helpers::*;
|
||||||
|
|
||||||
// Allocator
|
// Allocator
|
||||||
extern crate wee_alloc;
|
extern crate wee_alloc;
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
@ -56,6 +65,17 @@ fn take_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIErr
|
|||||||
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marshalling helpers
|
||||||
|
pub fn unmarshall(b64: String) -> Vec<u8> {
|
||||||
|
data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(b64.as_bytes())
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn marshall(data: &Vec<u8>) -> String {
|
||||||
|
data_encoding::BASE64URL_NOPAD.encode(data)
|
||||||
|
}
|
||||||
|
|
||||||
// JSON Helpers for WASM
|
// JSON Helpers for WASM
|
||||||
pub fn to_json<T: Serialize + Debug>(val: T) -> JsValue {
|
pub fn to_json<T: Serialize + Debug>(val: T) -> JsValue {
|
||||||
JsValue::from_str(&serialize_json(val))
|
JsValue::from_str(&serialize_json(val))
|
||||||
@ -112,6 +132,7 @@ where
|
|||||||
// WASM-specific
|
// WASM-specific
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidWASMConfigLoggingPerformance {
|
pub struct VeilidWASMConfigLoggingPerformance {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub level: veilid_core::VeilidConfigLogLevel,
|
pub level: veilid_core::VeilidConfigLogLevel,
|
||||||
@ -120,28 +141,38 @@ pub struct VeilidWASMConfigLoggingPerformance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidWASMConfigLoggingAPI {
|
pub struct VeilidWASMConfigLoggingAPI {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub level: veilid_core::VeilidConfigLogLevel,
|
pub level: veilid_core::VeilidConfigLogLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
pub struct VeilidWASMConfigLogging {
|
pub struct VeilidWASMConfigLogging {
|
||||||
pub performance: VeilidWASMConfigLoggingPerformance,
|
pub performance: VeilidWASMConfigLoggingPerformance,
|
||||||
pub api: VeilidWASMConfigLoggingAPI,
|
pub api: VeilidWASMConfigLoggingAPI,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi))]
|
||||||
pub struct VeilidWASMConfig {
|
pub struct VeilidWASMConfig {
|
||||||
pub logging: VeilidWASMConfigLogging,
|
pub logging: VeilidWASMConfigLogging,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[cfg_attr(
|
||||||
|
target_arch = "wasm32",
|
||||||
|
derive(Tsify),
|
||||||
|
tsify(from_wasm_abi, into_wasm_abi)
|
||||||
|
)]
|
||||||
pub struct VeilidRouteBlob {
|
pub struct VeilidRouteBlob {
|
||||||
pub route_id: veilid_core::RouteId,
|
pub route_id: veilid_core::RouteId,
|
||||||
#[serde(with = "veilid_core::as_human_base64")]
|
#[serde(with = "veilid_core::as_human_base64")]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", tsify(type = "string"))]
|
||||||
pub blob: Vec<u8>,
|
pub blob: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
from_impl_to_jsvalue!(VeilidRouteBlob);
|
||||||
|
|
||||||
// WASM Bindings
|
// WASM Bindings
|
||||||
|
|
||||||
@ -215,6 +246,11 @@ pub fn change_log_level(layer: String, log_level: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const IUPDATE_VEILID_FUNCTION: &'static str = r#"
|
||||||
|
type UpdateVeilidFunction = (event: VeilidUpdate) => void;
|
||||||
|
"#;
|
||||||
|
|
||||||
#[wasm_bindgen()]
|
#[wasm_bindgen()]
|
||||||
pub fn startup_veilid_core(update_callback_js: Function, json_config: String) -> Promise {
|
pub fn startup_veilid_core(update_callback_js: Function, json_config: String) -> Promise {
|
||||||
let update_callback_js = SendWrapper::new(update_callback_js);
|
let update_callback_js = SendWrapper::new(update_callback_js);
|
||||||
@ -378,7 +414,7 @@ pub fn routing_context_app_message(id: u32, target_string: String, message: Stri
|
|||||||
let routing_context = {
|
let routing_context = {
|
||||||
let rc = (*ROUTING_CONTEXTS).borrow();
|
let rc = (*ROUTING_CONTEXTS).borrow();
|
||||||
let Some(routing_context) = rc.get(&id) else {
|
let Some(routing_context) = rc.get(&id) else {
|
||||||
return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_app_call", "id", id));
|
return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_app_message", "id", id));
|
||||||
};
|
};
|
||||||
routing_context.clone()
|
routing_context.clone()
|
||||||
};
|
};
|
||||||
@ -1454,6 +1490,8 @@ pub fn veilid_version_string() -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
|
||||||
|
#[tsify(into_wasm_abi)]
|
||||||
pub struct VeilidVersion {
|
pub struct VeilidVersion {
|
||||||
pub major: u32,
|
pub major: u32,
|
||||||
pub minor: u32,
|
pub minor: u32,
|
||||||
|
169
veilid-wasm/src/veilid_client_js.rs
Normal file
169
veilid-wasm/src/veilid_client_js.rs
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const IUPDATE_VEILID_FUNCTION: &'static str = r#"
|
||||||
|
type UpdateVeilidFunction = (event: VeilidUpdate) => void;
|
||||||
|
"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(extends = Function, typescript_type = "UpdateVeilidFunction")]
|
||||||
|
pub type UpdateVeilidFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = veilidClient)]
|
||||||
|
pub struct VeilidClient {}
|
||||||
|
|
||||||
|
// Since this implementation doesn't contain a `new` fn that's marked as a constructor,
|
||||||
|
// and none of the member fns take a &self arg,
|
||||||
|
// this is just a namespace/class of static functions.
|
||||||
|
#[wasm_bindgen(js_class = veilidClient)]
|
||||||
|
impl VeilidClient {
|
||||||
|
pub async fn initializeCore(platformConfig: VeilidWASMConfig) {
|
||||||
|
if INITIALIZED.swap(true, Ordering::Relaxed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
|
// Set up subscriber and layers
|
||||||
|
let subscriber = Registry::default();
|
||||||
|
let mut layers = Vec::new();
|
||||||
|
let mut filters = (*FILTERS).borrow_mut();
|
||||||
|
|
||||||
|
// Performance logger
|
||||||
|
if platformConfig.logging.performance.enabled {
|
||||||
|
let filter =
|
||||||
|
veilid_core::VeilidLayerFilter::new(platformConfig.logging.performance.level, None);
|
||||||
|
let layer = WASMLayer::new(
|
||||||
|
WASMLayerConfigBuilder::new()
|
||||||
|
.set_report_logs_in_timings(platformConfig.logging.performance.logs_in_timings)
|
||||||
|
.set_console_config(if platformConfig.logging.performance.logs_in_console {
|
||||||
|
ConsoleConfig::ReportWithConsoleColor
|
||||||
|
} else {
|
||||||
|
ConsoleConfig::NoReporting
|
||||||
|
})
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.with_filter(filter.clone());
|
||||||
|
filters.insert("performance", filter);
|
||||||
|
layers.push(layer.boxed());
|
||||||
|
};
|
||||||
|
|
||||||
|
// API logger
|
||||||
|
if platformConfig.logging.api.enabled {
|
||||||
|
let filter =
|
||||||
|
veilid_core::VeilidLayerFilter::new(platformConfig.logging.api.level, None);
|
||||||
|
let layer = veilid_core::ApiTracingLayer::get().with_filter(filter.clone());
|
||||||
|
filters.insert("api", filter);
|
||||||
|
layers.push(layer.boxed());
|
||||||
|
}
|
||||||
|
|
||||||
|
let subscriber = subscriber.with(layers);
|
||||||
|
subscriber
|
||||||
|
.try_init()
|
||||||
|
.map_err(|e| format!("failed to initialize logging: {}", e))
|
||||||
|
.expect("failed to initalize WASM platform");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize a Veilid node, with the configuration in JSON format
|
||||||
|
///
|
||||||
|
/// Must be called only once at the start of an application
|
||||||
|
///
|
||||||
|
/// @param {UpdateVeilidFunction} update_callback_js - called when internal state of the Veilid node changes, for example, when app-level messages are received, when private routes die and need to be reallocated, or when routing table states change
|
||||||
|
/// @param {string} json_config - called at startup to supply a JSON configuration object.
|
||||||
|
pub async fn startupCore(
|
||||||
|
update_callback_js: UpdateVeilidFunction,
|
||||||
|
json_config: String,
|
||||||
|
) -> APIResult<()> {
|
||||||
|
let update_callback_js = SendWrapper::new(update_callback_js);
|
||||||
|
let update_callback = Arc::new(move |update: VeilidUpdate| {
|
||||||
|
let _ret = match Function::call1(
|
||||||
|
&update_callback_js,
|
||||||
|
&JsValue::UNDEFINED,
|
||||||
|
&to_jsvalue(update),
|
||||||
|
) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
console_log(&format!("calling update callback failed: {:?}", e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if VEILID_API.borrow().is_some() {
|
||||||
|
return APIResult::Err(veilid_core::VeilidAPIError::AlreadyInitialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
let veilid_api = veilid_core::api_startup_json(update_callback, json_config).await?;
|
||||||
|
VEILID_API.replace(Some(veilid_api));
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: can we refine the TS type of `layer`?
|
||||||
|
pub fn changeLogLevel(layer: String, log_level: VeilidConfigLogLevel) {
|
||||||
|
let layer = if layer == "all" { "".to_owned() } else { layer };
|
||||||
|
let filters = (*FILTERS).borrow();
|
||||||
|
if layer.is_empty() {
|
||||||
|
// Change all layers
|
||||||
|
for f in filters.values() {
|
||||||
|
f.set_max_level(log_level);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Change a specific layer
|
||||||
|
let f = filters.get(layer.as_str()).unwrap();
|
||||||
|
f.set_max_level(log_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shut down Veilid and terminate the API.
|
||||||
|
pub async fn shutdownCore() -> APIResult<()> {
|
||||||
|
let veilid_api = take_veilid_api()?;
|
||||||
|
veilid_api.shutdown().await;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a full copy of the current state of Veilid.
|
||||||
|
pub async fn getState() -> APIResult<VeilidState> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let core_state = veilid_api.get_state().await?;
|
||||||
|
APIResult::Ok(core_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect to the network.
|
||||||
|
pub async fn attach() -> APIResult<()> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
veilid_api.attach().await?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disconnect from the network.
|
||||||
|
pub async fn detach() -> APIResult<()> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
veilid_api.detach().await?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Execute an 'internal debug command'.
|
||||||
|
pub async fn debug(command: String) -> APIResult<String> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let out = veilid_api.debug(command).await?;
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the cargo package version of veilid-core, in object format.
|
||||||
|
pub fn version() -> VeilidVersion {
|
||||||
|
let (major, minor, patch) = veilid_core::veilid_version();
|
||||||
|
let vv = super::VeilidVersion {
|
||||||
|
major,
|
||||||
|
minor,
|
||||||
|
patch,
|
||||||
|
};
|
||||||
|
vv
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the cargo package version of veilid-core, in string format.
|
||||||
|
pub fn versionString() -> String {
|
||||||
|
veilid_core::veilid_version_string()
|
||||||
|
}
|
||||||
|
}
|
470
veilid-wasm/src/veilid_crypto_js.rs
Normal file
470
veilid-wasm/src/veilid_crypto_js.rs
Normal file
@ -0,0 +1,470 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "string[]")]
|
||||||
|
pub type ValidCryptoKinds;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = veilidCrypto)]
|
||||||
|
pub struct VeilidCrypto {}
|
||||||
|
|
||||||
|
// Since this implementation doesn't contain a `new` fn that's marked as a constructor,
|
||||||
|
// and none of the member fns take a &self arg,
|
||||||
|
// this is just a namespace/class of static functions.
|
||||||
|
#[wasm_bindgen(js_class = veilidCrypto)]
|
||||||
|
impl VeilidCrypto {
|
||||||
|
pub fn validCryptoKinds() -> StringArray {
|
||||||
|
let res = veilid_core::VALID_CRYPTO_KINDS
|
||||||
|
.iter()
|
||||||
|
.map(|k| (*k).to_string())
|
||||||
|
.collect();
|
||||||
|
into_unchecked_string_array(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bestCryptoKind() -> String {
|
||||||
|
veilid_core::best_crypto_kind().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cachedDh(kind: String, key: String, secret: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
let key: veilid_core::PublicKey = veilid_core::PublicKey::from_str(&key)?;
|
||||||
|
let secret: veilid_core::SecretKey = veilid_core::SecretKey::from_str(&secret)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_cached_dh",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.cached_dh(&key, &secret)?;
|
||||||
|
APIResult::Ok(out.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn computeDh(kind: String, key: String, secret: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let key: veilid_core::PublicKey = veilid_core::PublicKey::from_str(&key)?;
|
||||||
|
let secret: veilid_core::SecretKey = veilid_core::SecretKey::from_str(&secret)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_compute_dh",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.compute_dh(&key, &secret)?;
|
||||||
|
APIResult::Ok(out.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn randomBytes(kind: String, len: u32) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_random_bytes",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.random_bytes(len);
|
||||||
|
let out = data_encoding::BASE64URL_NOPAD.encode(&out);
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn defaultSaltLength(kind: String) -> APIResult<u32> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_default_salt_length",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.default_salt_length();
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hashPassword(kind: String, password: String, salt: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
let password: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(password.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
let salt: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(salt.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_hash_password",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.hash_password(&password, &salt)?;
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verifyPassword(
|
||||||
|
kind: String,
|
||||||
|
password: String,
|
||||||
|
password_hash: String,
|
||||||
|
) -> APIResult<bool> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
let password: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(password.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_verify_password",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.verify_password(&password, &password_hash)?;
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deriveSharedSecret(kind: String, password: String, salt: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
let password: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(password.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
let salt: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(salt.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_derive_shared_secret",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.derive_shared_secret(&password, &salt)?;
|
||||||
|
APIResult::Ok(out.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn randomNonce(kind: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_random_nonce",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.random_nonce();
|
||||||
|
APIResult::Ok(out.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn randomSharedSecret(kind: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_random_shared_secret",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.random_shared_secret();
|
||||||
|
APIResult::Ok(out.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generateKeyPair(kind: String) -> APIResult<KeyPair> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_generate_key_pair",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.generate_keypair();
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generateHash(kind: String, data: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(data.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_generate_hash",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.generate_hash(&data);
|
||||||
|
APIResult::Ok(out.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn validateKeyPair(kind: String, key: String, secret: String) -> APIResult<bool> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let key: veilid_core::PublicKey = veilid_core::PublicKey::from_str(&key)?;
|
||||||
|
let secret: veilid_core::SecretKey = veilid_core::SecretKey::from_str(&secret)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_validate_key_pair",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.validate_keypair(&key, &secret);
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn validateHash(kind: String, data: String, hash: String) -> APIResult<bool> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(data.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let hash: veilid_core::HashDigest = veilid_core::HashDigest::from_str(&hash)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_validate_hash",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.validate_hash(&data, &hash);
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn distance(kind: String, key1: String, key2: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let key1: veilid_core::CryptoKey = veilid_core::CryptoKey::from_str(&key1)?;
|
||||||
|
let key2: veilid_core::CryptoKey = veilid_core::CryptoKey::from_str(&key2)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_distance",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.distance(&key1, &key2);
|
||||||
|
APIResult::Ok(out.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sign(kind: String, key: String, secret: String, data: String) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let key: veilid_core::PublicKey = veilid_core::PublicKey::from_str(&key)?;
|
||||||
|
let secret: veilid_core::SecretKey = veilid_core::SecretKey::from_str(&secret)?;
|
||||||
|
|
||||||
|
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(data.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument("crypto_sign", "kind", kind.to_string())
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.sign(&key, &secret, &data)?;
|
||||||
|
APIResult::Ok(out.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(kind: String, key: String, data: String, signature: String) -> APIResult<()> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let key: veilid_core::PublicKey = veilid_core::PublicKey::from_str(&key)?;
|
||||||
|
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(data.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
let signature: veilid_core::Signature = veilid_core::Signature::from_str(&signature)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument("crypto_verify", "kind", kind.to_string())
|
||||||
|
})?;
|
||||||
|
crypto_system.verify(&key, &data, &signature)?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn aeadOverhead(kind: String) -> APIResult<usize> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_aead_overhead",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.aead_overhead();
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decryptAead(
|
||||||
|
kind: String,
|
||||||
|
body: String,
|
||||||
|
nonce: String,
|
||||||
|
shared_secret: String,
|
||||||
|
associated_data: Option<String>,
|
||||||
|
) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let body: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(body.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let nonce: veilid_core::Nonce = veilid_core::Nonce::from_str(&nonce)?;
|
||||||
|
|
||||||
|
let shared_secret: veilid_core::SharedSecret =
|
||||||
|
veilid_core::SharedSecret::from_str(&shared_secret)?;
|
||||||
|
|
||||||
|
let associated_data: Option<Vec<u8>> = associated_data.map(|ad| {
|
||||||
|
data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(ad.as_bytes())
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_decrypt_aead",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.decrypt_aead(
|
||||||
|
&body,
|
||||||
|
&nonce,
|
||||||
|
&shared_secret,
|
||||||
|
match &associated_data {
|
||||||
|
Some(ad) => Some(ad.as_slice()),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
let out = data_encoding::BASE64URL_NOPAD.encode(&out);
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encryptAead(
|
||||||
|
kind: String,
|
||||||
|
body: String,
|
||||||
|
nonce: String,
|
||||||
|
shared_secret: String,
|
||||||
|
associated_data: Option<String>,
|
||||||
|
) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let body: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(body.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let nonce: veilid_core::Nonce = veilid_core::Nonce::from_str(&nonce).unwrap();
|
||||||
|
|
||||||
|
let shared_secret: veilid_core::SharedSecret =
|
||||||
|
veilid_core::SharedSecret::from_str(&shared_secret).unwrap();
|
||||||
|
|
||||||
|
let associated_data: Option<Vec<u8>> = associated_data.map(|ad| {
|
||||||
|
data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(ad.as_bytes())
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_encrypt_aead",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let out = crypto_system.encrypt_aead(
|
||||||
|
&body,
|
||||||
|
&nonce,
|
||||||
|
&shared_secret,
|
||||||
|
match &associated_data {
|
||||||
|
Some(ad) => Some(ad.as_slice()),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
let out = data_encoding::BASE64URL_NOPAD.encode(&out);
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cryptNoAuth(
|
||||||
|
kind: String,
|
||||||
|
body: String,
|
||||||
|
nonce: String,
|
||||||
|
shared_secret: String,
|
||||||
|
) -> APIResult<String> {
|
||||||
|
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from_str(&kind)?;
|
||||||
|
|
||||||
|
let mut body: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(body.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let nonce: veilid_core::Nonce = veilid_core::Nonce::from_str(&nonce).unwrap();
|
||||||
|
|
||||||
|
let shared_secret: veilid_core::SharedSecret =
|
||||||
|
veilid_core::SharedSecret::from_str(&shared_secret).unwrap();
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let crypto = veilid_api.crypto()?;
|
||||||
|
let crypto_system = crypto.get(kind).ok_or_else(|| {
|
||||||
|
veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
"crypto_crypt_no_auth",
|
||||||
|
"kind",
|
||||||
|
kind.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
crypto_system.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret);
|
||||||
|
let out = data_encoding::BASE64URL_NOPAD.encode(&body);
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
}
|
333
veilid-wasm/src/veilid_routing_context_js.rs
Normal file
333
veilid-wasm/src/veilid_routing_context_js.rs
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen()]
|
||||||
|
pub struct VeilidRoutingContext {
|
||||||
|
inner_routing_context: Option<RoutingContext>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen()]
|
||||||
|
impl VeilidRoutingContext {
|
||||||
|
/// Don't use this constructor directly.
|
||||||
|
/// Use one of the `VeilidRoutingContext.create___()` factory methods instead.
|
||||||
|
/// @deprecated
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner_routing_context: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
// Constructor factories
|
||||||
|
// --------------------------------
|
||||||
|
|
||||||
|
/// Get a new RoutingContext object to use to send messages over the Veilid network.
|
||||||
|
pub fn createWithoutPrivacy() -> APIResult<VeilidRoutingContext> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let routing_context = veilid_api.routing_context();
|
||||||
|
Ok(VeilidRoutingContext {
|
||||||
|
inner_routing_context: Some(routing_context),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turn on sender privacy, enabling the use of safety routes.
|
||||||
|
///
|
||||||
|
/// Default values for hop count, stability and sequencing preferences are used.
|
||||||
|
///
|
||||||
|
/// Hop count default is dependent on config, but is set to 1 extra hop.
|
||||||
|
/// Stability default is to choose 'low latency' routes, preferring them over long-term reliability.
|
||||||
|
/// Sequencing default is to have no preference for ordered vs unordered message delivery
|
||||||
|
/// To modify these defaults, use `VeilidRoutingContext.createWithCustomPrivacy()`.
|
||||||
|
pub fn createWithPrivacy() -> APIResult<VeilidRoutingContext> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let routing_context = veilid_api.routing_context().with_privacy()?;
|
||||||
|
Ok(VeilidRoutingContext {
|
||||||
|
inner_routing_context: Some(routing_context),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turn on privacy using a custom `SafetySelection`
|
||||||
|
pub fn createWithCustomPrivacy(
|
||||||
|
safety_selection: SafetySelection,
|
||||||
|
) -> APIResult<VeilidRoutingContext> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let routing_context = veilid_api
|
||||||
|
.routing_context()
|
||||||
|
.with_custom_privacy(safety_selection)?;
|
||||||
|
Ok(VeilidRoutingContext {
|
||||||
|
inner_routing_context: Some(routing_context),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use a specified `Sequencing` preference, with or without privacy.
|
||||||
|
pub fn createWithSequencing(sequencing: Sequencing) -> APIResult<VeilidRoutingContext> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let routing_context = veilid_api.routing_context().with_sequencing(sequencing);
|
||||||
|
Ok(VeilidRoutingContext {
|
||||||
|
inner_routing_context: Some(routing_context),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
// Static methods
|
||||||
|
// --------------------------------
|
||||||
|
|
||||||
|
/// Allocate a new private route set with default cryptography and network options.
|
||||||
|
/// Returns a route id and a publishable 'blob' with the route encrypted with each crypto kind.
|
||||||
|
/// Those nodes importing the blob will have their choice of which crypto kind to use.
|
||||||
|
///
|
||||||
|
/// Returns a route id and 'blob' that can be published over some means (DHT or otherwise) to be imported by another Veilid node.
|
||||||
|
pub async fn newPrivateRoute() -> APIResult<VeilidRouteBlob> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
|
||||||
|
let (route_id, blob) = veilid_api.new_private_route().await?;
|
||||||
|
|
||||||
|
let route_blob = VeilidRouteBlob { route_id, blob };
|
||||||
|
APIResult::Ok(route_blob)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allocate a new private route and specify a specific cryptosystem, stability and sequencing preference.
|
||||||
|
/// Returns a route id and a publishable 'blob' with the route encrypted with each crypto kind.
|
||||||
|
/// Those nodes importing the blob will have their choice of which crypto kind to use.
|
||||||
|
///
|
||||||
|
/// Returns a route id and 'blob' that can be published over some means (DHT or otherwise) to be imported by another Veilid node.
|
||||||
|
pub async fn newCustomPrivateRoute(
|
||||||
|
stability: Stability,
|
||||||
|
sequencing: Sequencing,
|
||||||
|
) -> APIResult<VeilidRouteBlob> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
|
||||||
|
let (route_id, blob) = veilid_api
|
||||||
|
.new_custom_private_route(&veilid_core::VALID_CRYPTO_KINDS, stability, sequencing)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let route_blob = VeilidRouteBlob { route_id, blob };
|
||||||
|
APIResult::Ok(route_blob)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Release either a locally allocated or remotely imported private route.
|
||||||
|
///
|
||||||
|
/// This will deactivate the route and free its resources and it can no longer be sent to or received from.
|
||||||
|
pub fn releasePrivateRoute(route_id: String) -> APIResult<()> {
|
||||||
|
let route_id: veilid_core::RouteId = veilid_core::deserialize_json(&route_id).unwrap();
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
veilid_api.release_private_route(route_id)?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Respond to an AppCall received over a VeilidUpdate::AppCall.
|
||||||
|
///
|
||||||
|
/// * `call_id` - specifies which call to reply to, and it comes from a VeilidUpdate::AppCall, specifically the VeilidAppCall::id() value.
|
||||||
|
/// * `message` - is an answer blob to be returned by the remote node's RoutingContext::app_call() function, and may be up to 32768 bytes
|
||||||
|
pub async fn appCallReply(call_id: String, message: String) -> APIResult<()> {
|
||||||
|
let message = unmarshall(message);
|
||||||
|
let call_id = match call_id.parse() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument(
|
||||||
|
e, "call_id", call_id,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
veilid_api.app_call_reply(call_id, message).await?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
// Instance methods
|
||||||
|
// --------------------------------
|
||||||
|
fn getRoutingContext(&self) -> APIResult<RoutingContext> {
|
||||||
|
let Some(routing_context) = &self.inner_routing_context else {
|
||||||
|
return APIResult::Err(veilid_core::VeilidAPIError::generic("Unable to getRoutingContext instance. inner_routing_context is None."));
|
||||||
|
};
|
||||||
|
APIResult::Ok(routing_context.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// App-level unidirectional message that does not expect any value to be returned.
|
||||||
|
///
|
||||||
|
/// Veilid apps may use this for arbitrary message passing.
|
||||||
|
///
|
||||||
|
/// @param {string} target - can be either a direct node id or a private route.
|
||||||
|
/// @param {string} message - an arbitrary message blob of up to `32768` bytes.
|
||||||
|
#[wasm_bindgen(skip_jsdoc)]
|
||||||
|
pub async fn appMessage(&self, target_string: String, message: String) -> APIResult<()> {
|
||||||
|
let routing_context = self.getRoutingContext()?;
|
||||||
|
let message = unmarshall(message);
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let target = veilid_api.parse_as_target(target_string).await?;
|
||||||
|
routing_context.app_message(target, message).await?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// App-level bidirectional call that expects a response to be returned.
|
||||||
|
///
|
||||||
|
/// Veilid apps may use this for arbitrary message passing.
|
||||||
|
///
|
||||||
|
/// @param {string} target_string - can be either a direct node id or a private route, base64Url encoded.
|
||||||
|
/// @param {string} message - an arbitrary message blob of up to `32768` bytes, base64Url encoded.
|
||||||
|
/// @returns an answer blob of up to `32768` bytes, base64Url encoded.
|
||||||
|
#[wasm_bindgen(skip_jsdoc)]
|
||||||
|
pub async fn appCall(&self, target_string: String, request: String) -> APIResult<String> {
|
||||||
|
let request: Vec<u8> = unmarshall(request);
|
||||||
|
let routing_context = self.getRoutingContext()?;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let target = veilid_api.parse_as_target(target_string).await?;
|
||||||
|
let answer = routing_context.app_call(target, request).await?;
|
||||||
|
let answer = marshall(&answer);
|
||||||
|
APIResult::Ok(answer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// DHT Records Creates a new DHT record a specified crypto kind and schema
|
||||||
|
///
|
||||||
|
/// The record is considered 'open' after the create operation succeeds.
|
||||||
|
///
|
||||||
|
/// @returns the newly allocated DHT record's key if successful.
|
||||||
|
pub async fn createDhtRecord(
|
||||||
|
&self,
|
||||||
|
schema: DHTSchema,
|
||||||
|
kind: String,
|
||||||
|
) -> APIResult<DHTRecordDescriptor> {
|
||||||
|
let crypto_kind = if kind.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(veilid_core::FourCC::from_str(&kind)?)
|
||||||
|
};
|
||||||
|
let routing_context = self.getRoutingContext()?;
|
||||||
|
|
||||||
|
let dht_record_descriptor = routing_context
|
||||||
|
.create_dht_record(schema, crypto_kind)
|
||||||
|
.await?;
|
||||||
|
APIResult::Ok(dht_record_descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Opens a DHT record at a specific key.
|
||||||
|
///
|
||||||
|
/// Associates a secret if one is provided to provide writer capability. Records may only be opened or created. To re-open with a different routing context, first close the value.
|
||||||
|
///
|
||||||
|
/// @returns the DHT record descriptor for the opened record if successful.
|
||||||
|
/// @param {string} writer - Stringified key pair, in the form of `key:secret` where `key` and `secret` are base64Url encoded.
|
||||||
|
/// @param {string} key - key of the DHT record.
|
||||||
|
#[wasm_bindgen(skip_jsdoc)]
|
||||||
|
pub async fn openDhtRecord(
|
||||||
|
&self,
|
||||||
|
key: String,
|
||||||
|
writer: Option<String>,
|
||||||
|
) -> APIResult<DHTRecordDescriptor> {
|
||||||
|
let key = TypedKey::from_str(&key).unwrap();
|
||||||
|
let writer = match writer {
|
||||||
|
Some(writer) => Some(KeyPair::from_str(&writer).unwrap()),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let routing_context = self.getRoutingContext()?;
|
||||||
|
let dht_record_descriptor = routing_context.open_dht_record(key, writer).await?;
|
||||||
|
APIResult::Ok(dht_record_descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Closes a DHT record at a specific key that was opened with create_dht_record or open_dht_record.
|
||||||
|
///
|
||||||
|
/// Closing a record allows you to re-open it with a different routing context
|
||||||
|
pub async fn closeDhtRecord(&self, key: String) -> APIResult<()> {
|
||||||
|
let key = TypedKey::from_str(&key).unwrap();
|
||||||
|
let routing_context = self.getRoutingContext()?;
|
||||||
|
routing_context.close_dht_record(key).await?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes a DHT record at a specific key
|
||||||
|
///
|
||||||
|
/// If the record is opened, it must be closed before it is deleted.
|
||||||
|
/// Deleting a record does not delete it from the network, but will remove the storage of the record locally,
|
||||||
|
/// and will prevent its value from being refreshed on the network by this node.
|
||||||
|
pub async fn deleteDhtRecord(&self, key: String) -> APIResult<()> {
|
||||||
|
let key = TypedKey::from_str(&key).unwrap();
|
||||||
|
let routing_context = self.getRoutingContext()?;
|
||||||
|
routing_context.delete_dht_record(key).await?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the latest value of a subkey.
|
||||||
|
///
|
||||||
|
/// May pull the latest value from the network, but by settings 'force_refresh' you can force a network data refresh.
|
||||||
|
///
|
||||||
|
/// Returns `undefined` if the value subkey has not yet been set.
|
||||||
|
/// Returns base64Url encoded `data` if the value subkey has valid data.
|
||||||
|
pub async fn getDhtValue(
|
||||||
|
&self,
|
||||||
|
key: String,
|
||||||
|
subKey: u32,
|
||||||
|
forceRefresh: bool,
|
||||||
|
) -> APIResult<Option<ValueData>> {
|
||||||
|
let key = TypedKey::from_str(&key).unwrap();
|
||||||
|
let routing_context = self.getRoutingContext()?;
|
||||||
|
let res = routing_context
|
||||||
|
.get_dht_value(key, subKey, forceRefresh)
|
||||||
|
.await?;
|
||||||
|
APIResult::Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pushes a changed subkey value to the network
|
||||||
|
///
|
||||||
|
/// Returns `undefined` if the value was successfully put.
|
||||||
|
/// Returns base64Url encoded `data` if the value put was older than the one available on the network.
|
||||||
|
pub async fn setDhtValue(
|
||||||
|
&self,
|
||||||
|
key: String,
|
||||||
|
subKey: u32,
|
||||||
|
data: String,
|
||||||
|
) -> APIResult<Option<ValueData>> {
|
||||||
|
let key = TypedKey::from_str(&key).unwrap();
|
||||||
|
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(&data.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let routing_context = self.getRoutingContext()?;
|
||||||
|
let res = routing_context.set_dht_value(key, subKey, data).await?;
|
||||||
|
APIResult::Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub async fn watchDhtValues(
|
||||||
|
// &self,
|
||||||
|
// key: String,
|
||||||
|
// subKeys: ValueSubkeyRangeSet,
|
||||||
|
// expiration: Timestamp,
|
||||||
|
// count: u32,
|
||||||
|
// ) -> APIResult<String> {
|
||||||
|
// let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap();
|
||||||
|
// let subkeys: veilid_core::ValueSubkeyRangeSet =
|
||||||
|
// veilid_core::deserialize_json(&subkeys).unwrap();
|
||||||
|
// let expiration = veilid_core::Timestamp::from_str(&expiration).unwrap();
|
||||||
|
|
||||||
|
// let routing_context = {
|
||||||
|
// let rc = (*ROUTING_CONTEXTS).borrow();
|
||||||
|
// let Some(routing_context) = rc.get(&id) else {
|
||||||
|
// return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_watch_dht_values", "id", self.id));
|
||||||
|
// };
|
||||||
|
// routing_context.clone()
|
||||||
|
// };
|
||||||
|
// let res = routing_context
|
||||||
|
// .watch_dht_values(key, subkeys, expiration, count)
|
||||||
|
// .await?;
|
||||||
|
// APIResult::Ok(res.to_string())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub async fn cancelDhtWatch(id: u32, key: String, subkeys: String) -> Promise {
|
||||||
|
// let key: veilid_core::TypedKey = veilid_core::deserialize_json(&key).unwrap();
|
||||||
|
// let subkeys: veilid_core::ValueSubkeyRangeSet =
|
||||||
|
// veilid_core::deserialize_json(&subkeys).unwrap();
|
||||||
|
|
||||||
|
// let routing_context = {
|
||||||
|
// let rc = (*ROUTING_CONTEXTS).borrow();
|
||||||
|
// let Some(routing_context) = rc.get(&id) else {
|
||||||
|
// return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_cancel_dht_watch", "id", self.id));
|
||||||
|
// };
|
||||||
|
// routing_context.clone()
|
||||||
|
// };
|
||||||
|
// let res = routing_context.cancel_dht_watch(key, subkeys).await?;
|
||||||
|
// APIResult::Ok(res)
|
||||||
|
// }
|
||||||
|
}
|
176
veilid-wasm/src/veilid_table_db_js.rs
Normal file
176
veilid-wasm/src/veilid_table_db_js.rs
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen()]
|
||||||
|
pub struct VeilidTableDB {
|
||||||
|
inner_table_db: Option<TableDB>,
|
||||||
|
tableName: String,
|
||||||
|
columnCount: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen()]
|
||||||
|
impl VeilidTableDB {
|
||||||
|
/// If the column count is greater than an existing TableDB's column count,
|
||||||
|
/// the database will be upgraded to add the missing columns.
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
pub fn new(tableName: String, columnCount: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
inner_table_db: None,
|
||||||
|
tableName,
|
||||||
|
columnCount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getTableDB(&self) -> APIResult<TableDB> {
|
||||||
|
let Some(table_db) = &self.inner_table_db else {
|
||||||
|
return APIResult::Err(veilid_core::VeilidAPIError::generic("Unable to getTableDB instance. Ensure you've called openTable()."));
|
||||||
|
};
|
||||||
|
APIResult::Ok(table_db.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get or create the TableDB database table.
|
||||||
|
/// This is called automatically when performing actions on the TableDB.
|
||||||
|
pub async fn openTable(&mut self) -> APIResult<()> {
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let tstore = veilid_api.table_store()?;
|
||||||
|
let table_db = tstore
|
||||||
|
.open(&self.tableName, self.columnCount)
|
||||||
|
.await
|
||||||
|
.map_err(veilid_core::VeilidAPIError::generic)?;
|
||||||
|
self.inner_table_db = Some(table_db);
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete this TableDB.
|
||||||
|
pub async fn deleteTable(&mut self) -> APIResult<bool> {
|
||||||
|
self.inner_table_db = None;
|
||||||
|
|
||||||
|
let veilid_api = get_veilid_api()?;
|
||||||
|
let tstore = veilid_api.table_store()?;
|
||||||
|
let deleted = tstore
|
||||||
|
.delete(&self.tableName)
|
||||||
|
.await
|
||||||
|
.map_err(veilid_core::VeilidAPIError::generic)?;
|
||||||
|
APIResult::Ok(deleted)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn ensureOpen(&mut self) {
|
||||||
|
if self.inner_table_db.is_none() {
|
||||||
|
let _ = self.openTable().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a key from a column in the TableDB immediately.
|
||||||
|
pub async fn load(&mut self, columnId: u32, key: String) -> APIResult<Option<String>> {
|
||||||
|
self.ensureOpen().await;
|
||||||
|
let key = unmarshall(key);
|
||||||
|
let table_db = self.getTableDB()?;
|
||||||
|
|
||||||
|
let out = table_db.load(columnId, &key).await?.unwrap();
|
||||||
|
let out = Some(marshall(&out));
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Store a key with a value in a column in the TableDB.
|
||||||
|
/// Performs a single transaction immediately.
|
||||||
|
pub async fn store(&mut self, columnId: u32, key: String, value: String) -> APIResult<()> {
|
||||||
|
self.ensureOpen().await;
|
||||||
|
let key = unmarshall(key);
|
||||||
|
let value = unmarshall(value);
|
||||||
|
let table_db = self.getTableDB()?;
|
||||||
|
|
||||||
|
table_db.store(columnId, &key, &value).await?;
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete key with from a column in the TableDB.
|
||||||
|
pub async fn delete(&mut self, columnId: u32, key: String) -> APIResult<Option<String>> {
|
||||||
|
self.ensureOpen().await;
|
||||||
|
let key = unmarshall(key);
|
||||||
|
let table_db = self.getTableDB()?;
|
||||||
|
|
||||||
|
let out = table_db.delete(columnId, &key).await?.unwrap();
|
||||||
|
let out = Some(marshall(&out));
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of keys in a column of the TableDB.
|
||||||
|
///
|
||||||
|
/// Returns an array of base64Url encoded keys.
|
||||||
|
pub async fn getKeys(&mut self, columnId: u32) -> APIResult<StringArray> {
|
||||||
|
self.ensureOpen().await;
|
||||||
|
let table_db = self.getTableDB()?;
|
||||||
|
|
||||||
|
let keys = table_db.clone().get_keys(columnId).await?;
|
||||||
|
let out: Vec<String> = keys.into_iter().map(|k| marshall(&k)).collect();
|
||||||
|
let out = into_unchecked_string_array(out);
|
||||||
|
|
||||||
|
APIResult::Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start a TableDB write transaction.
|
||||||
|
/// The transaction object must be committed or rolled back before dropping.
|
||||||
|
pub async fn createTransaction(&mut self) -> APIResult<VeilidTableDBTransaction> {
|
||||||
|
self.ensureOpen().await;
|
||||||
|
let table_db = self.getTableDB()?;
|
||||||
|
|
||||||
|
let transaction = table_db.transact();
|
||||||
|
APIResult::Ok(VeilidTableDBTransaction {
|
||||||
|
inner_transaction: Some(transaction),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct VeilidTableDBTransaction {
|
||||||
|
inner_transaction: Option<TableDBTransaction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl VeilidTableDBTransaction {
|
||||||
|
/// Don't use this constructor directly.
|
||||||
|
/// Use `.createTransaction()` on an instance of `VeilidTableDB` instead.
|
||||||
|
/// @deprecated
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner_transaction: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getTransaction(&self) -> APIResult<TableDBTransaction> {
|
||||||
|
let Some(transaction) = &self.inner_transaction else {
|
||||||
|
return APIResult::Err(veilid_core::VeilidAPIError::generic("Unable to getTransaction instance. inner_transaction is None."));
|
||||||
|
};
|
||||||
|
APIResult::Ok(transaction.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Commit the transaction. Performs all actions atomically.
|
||||||
|
pub async fn commit(&self) -> APIResult<()> {
|
||||||
|
let transaction = self.getTransaction()?;
|
||||||
|
transaction.commit().await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rollback the transaction. Does nothing to the TableDB.
|
||||||
|
pub fn rollback(&self) -> APIResult<()> {
|
||||||
|
let transaction = self.getTransaction()?;
|
||||||
|
transaction.rollback();
|
||||||
|
APIRESULT_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Store a key with a value in a column in the TableDB.
|
||||||
|
/// Does not modify TableDB until `.commit()` is called.
|
||||||
|
pub fn store(&self, col: u32, key: String, value: String) -> APIResult<()> {
|
||||||
|
let key = unmarshall(key);
|
||||||
|
let value = unmarshall(value);
|
||||||
|
let transaction = self.getTransaction()?;
|
||||||
|
transaction.store(col, &key, &value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete key with from a column in the TableDB
|
||||||
|
pub fn deleteKey(&self, col: u32, key: String) -> APIResult<()> {
|
||||||
|
let key = unmarshall(key);
|
||||||
|
let transaction = self.getTransaction()?;
|
||||||
|
transaction.delete(col, &key)
|
||||||
|
}
|
||||||
|
}
|
38
veilid-wasm/src/wasm_helpers.rs
Normal file
38
veilid-wasm/src/wasm_helpers.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_arch = "wasm32")] {
|
||||||
|
pub use tsify::*;
|
||||||
|
pub use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
macro_rules! from_impl_to_jsvalue {
|
||||||
|
($name: ident) => {
|
||||||
|
impl From<$name> for JsValue {
|
||||||
|
fn from(value: $name) -> Self {
|
||||||
|
serde_wasm_bindgen::to_value(&value).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
macro_rules! from_impl_to_jsvalue {
|
||||||
|
($name: ident) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) use from_impl_to_jsvalue;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "string[]")]
|
||||||
|
pub type StringArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a `Vec<String>` into a `js_sys::Array` with the type of `string[]`
|
||||||
|
pub(crate) fn into_unchecked_string_array(items: Vec<String>) -> StringArray {
|
||||||
|
items
|
||||||
|
.iter()
|
||||||
|
.map(JsValue::from)
|
||||||
|
.collect::<js_sys::Array>()
|
||||||
|
.unchecked_into::<StringArray>() // TODO: can I do this a better way?
|
||||||
|
}
|
@ -1,182 +1,218 @@
|
|||||||
//! Test suite for the Web and headless browsers.
|
//! Test suite for the Web and headless browsers.
|
||||||
|
//! These tests only work with WASM_BINDGEN_USE_NO_MODULE=true env var,
|
||||||
//XXXXXXXXXXXXXXX
|
//! as otherwise there's no way to access the generated wasm bindings from inside JS.
|
||||||
//XXX DOES NOT WORK.
|
|
||||||
|
|
||||||
#![cfg(target_arch = "wasm32")]
|
#![cfg(target_arch = "wasm32")]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate wasm_bindgen_test;
|
extern crate wasm_bindgen_test;
|
||||||
use core::sync::atomic::AtomicBool;
|
use js_sys::*;
|
||||||
|
use parking_lot::Once;
|
||||||
use veilid_wasm::*;
|
use veilid_wasm::*;
|
||||||
|
use wasm_bindgen::*;
|
||||||
|
use wasm_bindgen_futures::*;
|
||||||
use wasm_bindgen_test::*;
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
wasm_bindgen_test_configure!(run_in_browser);
|
wasm_bindgen_test_configure!(run_in_browser);
|
||||||
|
|
||||||
static SETUP_ONCE: AtomicBool = AtomicBool::new(false);
|
static SETUP_ONCE: Once = Once::new();
|
||||||
pub fn setup() -> () {
|
pub fn setup() -> () {
|
||||||
if SETUP_ONCE
|
SETUP_ONCE.call_once(|| {
|
||||||
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
console_log!("setup()");
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
console_log("setup()");
|
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
wasm_logger::init(wasm_logger::Config::new(Level::Trace));
|
|
||||||
init_callbacks();
|
init_callbacks();
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
// xxx needs updating to new keys and veilid_api object
|
|
||||||
fn init_callbacks() {
|
fn init_callbacks() {
|
||||||
assert_eq!(js_sys::eval(r#"
|
assert_eq!(js_sys::eval(r#"
|
||||||
window.sleep = (milliseconds) => { return new Promise(resolve => setTimeout(resolve, milliseconds)) };
|
window.sleep = (milliseconds) => { return new Promise(resolve => setTimeout(resolve, milliseconds)) };
|
||||||
window.stateChangeCallback = async (stateChange) => { console.log("State change: " + stateChange); };
|
window.stateChangeCallback = async (stateChange) => {
|
||||||
window.configCallback = (configKey) => {
|
delete stateChange.peers; // makes logs less verbose
|
||||||
switch(configKey) {
|
console.log("State change: ", JSON.stringify(stateChange, null, 2));
|
||||||
case "namespace": return "";
|
|
||||||
case "capabilities.disable": return [];
|
|
||||||
case "tablestore.directory": return "";
|
|
||||||
case "network.routing_table.node_id": return [];
|
|
||||||
case "network.routing_table.node_id_secret": return [];
|
|
||||||
case "network.routing_table.bootstrap": return [];
|
|
||||||
case "network.routing_table.limit_over_attached": return 64;
|
|
||||||
case "network.routing_table.limit_fully_attached": return 32;
|
|
||||||
case "network.routing_table.limit_attached_strong": return 16;
|
|
||||||
case "network.routing_table.limit_attached_good": return 8;
|
|
||||||
case "network.routing_table.limit_attached_weak": return 4;
|
|
||||||
case "network.rpc.concurrency": return 2;
|
|
||||||
case "network.rpc.queue_size": return 128;
|
|
||||||
case "network.rpc.max_timestamp_behind": return 10000000;
|
|
||||||
case "network.rpc.max_timestamp_ahead": return 10000000;
|
|
||||||
case "network.rpc.timeout": return 10000000;
|
|
||||||
case "network.rpc.max_route_hop_count": return 4;
|
|
||||||
case "network.rpc.default_route_hop_count": return 1;
|
|
||||||
case "network.dht.max_find_node_count": return 20;
|
|
||||||
case "network.dht.resolve_node_timeout": return 10000;
|
|
||||||
case "network.dht.resolve_node_count": return 1;
|
|
||||||
case "network.dht.resolve_node_fanout": return 4;
|
|
||||||
case "network.dht.get_value_timeout": return 10000;
|
|
||||||
case "network.dht.get_value_count": return 3;
|
|
||||||
case "network.dht.get_value_fanout": return 4;
|
|
||||||
case "network.dht.set_value_timeout": return 10000;
|
|
||||||
case "network.dht.set_value_count": return 5;
|
|
||||||
case "network.dht.set_value_fanout": return 4;
|
|
||||||
case "network.dht.min_peer_count": return 20;
|
|
||||||
case "network.dht.min_peer_refresh_time": return 2000000;
|
|
||||||
case "network.dht.validate_dial_info_receipt_time": return 5000000;
|
|
||||||
case "network.upnp": return false;
|
|
||||||
case "network.detect_address_changes": return true;
|
|
||||||
case "network.address_filter": return true;
|
|
||||||
case "network.restricted_nat_retries": return 3;
|
|
||||||
case "network.tls.certificate_path": return "";
|
|
||||||
case "network.tls.private_key_path": return "";
|
|
||||||
case "network.application.path": return "/app";
|
|
||||||
case "network.application.https.enabled": return false;
|
|
||||||
case "network.application.https.listen_address": return "";
|
|
||||||
case "network.application.http.enabled": return false;
|
|
||||||
case "network.application.http.listen_address": return "";
|
|
||||||
case "network.protocol.udp.enabled": return false;
|
|
||||||
case "network.protocol.udp.socket_pool_size": return 0;
|
|
||||||
case "network.protocol.udp.listen_address": return "";
|
|
||||||
case "network.protocol.udp.public_address": return "";
|
|
||||||
case "network.protocol.tcp.connect": return false;
|
|
||||||
case "network.protocol.tcp.listen": return false;
|
|
||||||
case "network.protocol.tcp.max_connections": return 32;
|
|
||||||
case "network.protocol.tcp.listen_address": return "";
|
|
||||||
case "network.protocol.tcp.public_address": return "";
|
|
||||||
case "network.protocol.ws.connect": return true;
|
|
||||||
case "network.protocol.ws.listen": return false;
|
|
||||||
case "network.protocol.ws.max_connections": return 16;
|
|
||||||
case "network.protocol.ws.listen_address": return "";
|
|
||||||
case "network.protocol.ws.path": return "/ws";
|
|
||||||
case "network.protocol.ws.public_address": return "";
|
|
||||||
case "network.protocol.wss.connect": return true;
|
|
||||||
case "network.protocol.wss.listen": return false;
|
|
||||||
case "network.protocol.wss.max_connections": return 16;
|
|
||||||
case "network.protocol.wss.listen_address": return "";
|
|
||||||
case "network.protocol.wss.path": return "/ws";
|
|
||||||
case "network.protocol.wss.public_address": return "";
|
|
||||||
default:
|
|
||||||
console.log("config key '" + key +"' doesn't exist"); break;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
window.veilidCoreInitConfig = {
|
||||||
|
logging: {
|
||||||
|
api: {
|
||||||
|
enabled: true,
|
||||||
|
level: 'Info',
|
||||||
|
},
|
||||||
|
performance: {
|
||||||
|
enabled: false,
|
||||||
|
level: 'Info',
|
||||||
|
logs_in_timings: false,
|
||||||
|
logs_in_console: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
window.veilidCoreStartupConfig = {
|
||||||
|
program_name: 'veilid-wasm-test',
|
||||||
|
namespace: '',
|
||||||
|
capabilities: {
|
||||||
|
disable: [],
|
||||||
|
},
|
||||||
|
protected_store: {
|
||||||
|
allow_insecure_fallback: true,
|
||||||
|
always_use_insecure_storage: true,
|
||||||
|
directory: '',
|
||||||
|
delete: false,
|
||||||
|
device_encryption_key_password: 'some-user-secret-value',
|
||||||
|
// "new_device_encryption_key_password": "an-updated-user-secret-value"
|
||||||
|
},
|
||||||
|
table_store: {
|
||||||
|
directory: '',
|
||||||
|
delete: false,
|
||||||
|
},
|
||||||
|
block_store: {
|
||||||
|
directory: '',
|
||||||
|
delete: false,
|
||||||
|
},
|
||||||
|
network: {
|
||||||
|
connection_initial_timeout_ms: 2000,
|
||||||
|
connection_inactivity_timeout_ms: 60000,
|
||||||
|
max_connections_per_ip4: 32,
|
||||||
|
max_connections_per_ip6_prefix: 32,
|
||||||
|
max_connections_per_ip6_prefix_size: 56,
|
||||||
|
max_connection_frequency_per_min: 128,
|
||||||
|
client_whitelist_timeout_ms: 300000,
|
||||||
|
reverse_connection_receipt_time_ms: 5000,
|
||||||
|
hole_punch_receipt_time_ms: 5000,
|
||||||
|
network_key_password: '',
|
||||||
|
disable_capabilites: [],
|
||||||
|
routing_table: {
|
||||||
|
node_id: [],
|
||||||
|
node_id_secret: [],
|
||||||
|
bootstrap: [
|
||||||
|
'ws://bootstrap.veilid.net:5150/ws',
|
||||||
|
],
|
||||||
|
limit_over_attached: 64,
|
||||||
|
limit_fully_attached: 32,
|
||||||
|
limit_attached_strong: 16,
|
||||||
|
limit_attached_good: 8,
|
||||||
|
limit_attached_weak: 4,
|
||||||
|
},
|
||||||
|
rpc: {
|
||||||
|
concurrency: 0,
|
||||||
|
queue_size: 1024,
|
||||||
|
max_timestamp_behind_ms: 10000,
|
||||||
|
max_timestamp_ahead_ms: 10000,
|
||||||
|
timeout_ms: 5000,
|
||||||
|
max_route_hop_count: 4,
|
||||||
|
default_route_hop_count: 1,
|
||||||
|
},
|
||||||
|
dht: {
|
||||||
|
max_find_node_count: 20,
|
||||||
|
resolve_node_timeout_ms: 10000,
|
||||||
|
resolve_node_count: 1,
|
||||||
|
resolve_node_fanout: 4,
|
||||||
|
get_value_timeout_ms: 10000,
|
||||||
|
get_value_count: 3,
|
||||||
|
get_value_fanout: 4,
|
||||||
|
set_value_timeout_ms: 10000,
|
||||||
|
set_value_count: 5,
|
||||||
|
set_value_fanout: 4,
|
||||||
|
min_peer_count: 20,
|
||||||
|
min_peer_refresh_time_ms: 60000,
|
||||||
|
validate_dial_info_receipt_time_ms: 2000,
|
||||||
|
local_subkey_cache_size: 128,
|
||||||
|
local_max_subkey_cache_memory_mb: 256,
|
||||||
|
remote_subkey_cache_size: 1024,
|
||||||
|
remote_max_records: 65536,
|
||||||
|
remote_max_subkey_cache_memory_mb: 256,
|
||||||
|
remote_max_storage_space_mb: 0,
|
||||||
|
},
|
||||||
|
upnp: true,
|
||||||
|
detect_address_changes: true,
|
||||||
|
restricted_nat_retries: 0,
|
||||||
|
tls: {
|
||||||
|
certificate_path: '',
|
||||||
|
private_key_path: '',
|
||||||
|
connection_initial_timeout_ms: 2000,
|
||||||
|
},
|
||||||
|
application: {
|
||||||
|
https: {
|
||||||
|
enabled: false,
|
||||||
|
listen_address: ':5150',
|
||||||
|
path: 'app',
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
enabled: false,
|
||||||
|
listen_address: ':5150',
|
||||||
|
path: 'app',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
protocol: {
|
||||||
|
udp: {
|
||||||
|
enabled: false,
|
||||||
|
socket_pool_size: 0,
|
||||||
|
listen_address: '',
|
||||||
|
},
|
||||||
|
tcp: {
|
||||||
|
connect: false,
|
||||||
|
listen: false,
|
||||||
|
max_connections: 32,
|
||||||
|
listen_address: '',
|
||||||
|
},
|
||||||
|
ws: {
|
||||||
|
connect: true,
|
||||||
|
listen: true,
|
||||||
|
max_connections: 16,
|
||||||
|
listen_address: ':5150',
|
||||||
|
path: 'ws',
|
||||||
|
},
|
||||||
|
wss: {
|
||||||
|
connect: true,
|
||||||
|
listen: false,
|
||||||
|
max_connections: 16,
|
||||||
|
listen_address: '',
|
||||||
|
path: 'ws',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
true
|
true
|
||||||
"#).expect("failed to eval"), JsValue::TRUE);
|
"#).expect("failed to eval"), JsValue::TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
/// Helper for converting an eval Promise result into a JsValue
|
||||||
///
|
async fn eval_promise(source: &str) -> JsValue {
|
||||||
|
JsFuture::from(
|
||||||
#[wasm_bindgen_test]
|
eval(source)
|
||||||
fn test_construct() {
|
.expect("Failed to eval")
|
||||||
setup();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
js_sys::eval(
|
|
||||||
r#"
|
|
||||||
let vc = new VeilidCore();
|
|
||||||
true
|
|
||||||
"#
|
|
||||||
)
|
|
||||||
.expect("failed to eval"),
|
|
||||||
JsValue::TRUE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen_test(async)]
|
|
||||||
async fn test_startup_shutdown() {
|
|
||||||
setup();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
JsFuture::from(
|
|
||||||
js_sys::eval(
|
|
||||||
r#"
|
|
||||||
(async function() {
|
|
||||||
let vc = new VeilidCore();
|
|
||||||
await vc.startup(window.stateChangeCallback, window.configCallback);
|
|
||||||
await vc.shutdown();
|
|
||||||
return true;
|
|
||||||
})().then(v => {
|
|
||||||
console.log("finished: " + v);
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
"#
|
|
||||||
)
|
|
||||||
.expect("failed to eval")
|
|
||||||
.dyn_into::<Promise>()
|
.dyn_into::<Promise>()
|
||||||
.unwrap()
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.await,
|
.await
|
||||||
Ok(JsValue::TRUE)
|
.unwrap()
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen_test(async)]
|
// ----------------------------------------------------------------
|
||||||
async fn test_attach_detach() {
|
|
||||||
|
// TODO: now that veilidClient uses a single instance of VeilidAPI,
|
||||||
|
// subsequent tests fail because veilidCore has already been initialized.
|
||||||
|
#[wasm_bindgen_test()]
|
||||||
|
async fn test_kitchen_sink() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
assert_eq!(
|
let res = eval_promise(
|
||||||
JsFuture::from(
|
r#"
|
||||||
js_sys::eval(
|
(async function () {
|
||||||
r#"
|
const { veilidClient } = wasm_bindgen; // only accessible in no_module mode.
|
||||||
(async function() {
|
veilidClient.initializeCore(window.veilidCoreInitConfig);
|
||||||
let vc = new VeilidCore();
|
await veilidClient.startupCore(window.stateChangeCallback, JSON.stringify(window.veilidCoreStartupConfig));
|
||||||
await vc.startup(window.stateChangeCallback, window.configCallback);
|
|
||||||
await vc.attach();
|
console.log(veilidClient.versionString());
|
||||||
await window.sleep(1000);
|
await veilidClient.attach();
|
||||||
await vc.detach();
|
|
||||||
await vc.shutdown();
|
await sleep(10000);
|
||||||
return true;
|
await veilidClient.detach();
|
||||||
})().then(v => {
|
await veilidClient.shutdownCore();
|
||||||
console.log("finished: " + v);
|
|
||||||
return v;
|
return true;
|
||||||
});
|
})();
|
||||||
"#
|
"#,
|
||||||
)
|
).await;
|
||||||
.expect("failed to eval")
|
|
||||||
.dyn_into::<Promise>()
|
assert_eq!(res, JsValue::TRUE);
|
||||||
.unwrap()
|
|
||||||
)
|
|
||||||
.await,
|
|
||||||
Ok(JsValue::TRUE)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ if [[ "$1" == "release" ]]; then
|
|||||||
|
|
||||||
cargo build --target wasm32-unknown-unknown --release
|
cargo build --target wasm32-unknown-unknown --release
|
||||||
mkdir -p $OUTPUTDIR
|
mkdir -p $OUTPUTDIR
|
||||||
wasm-bindgen --out-dir $OUTPUTDIR --target web $INPUTDIR/veilid_wasm.wasm
|
wasm-bindgen --out-dir $OUTPUTDIR --target web --weak-refs $INPUTDIR/veilid_wasm.wasm
|
||||||
wasm-strip $OUTPUTDIR/veilid_wasm_bg.wasm
|
wasm-strip $OUTPUTDIR/veilid_wasm_bg.wasm
|
||||||
else
|
else
|
||||||
OUTPUTDIR=../target/wasm32-unknown-unknown/debug/pkg
|
OUTPUTDIR=../target/wasm32-unknown-unknown/debug/pkg
|
||||||
@ -45,7 +45,7 @@ else
|
|||||||
|
|
||||||
RUSTFLAGS="-O -g $RUSTFLAGS" cargo build --target wasm32-unknown-unknown
|
RUSTFLAGS="-O -g $RUSTFLAGS" cargo build --target wasm32-unknown-unknown
|
||||||
mkdir -p $OUTPUTDIR
|
mkdir -p $OUTPUTDIR
|
||||||
wasm-bindgen --out-dir $OUTPUTDIR --target web --keep-debug --debug $INPUTDIR/veilid_wasm.wasm
|
wasm-bindgen --out-dir $OUTPUTDIR --target web --weak-refs --keep-debug --debug $INPUTDIR/veilid_wasm.wasm
|
||||||
./wasm-sourcemap.py $OUTPUTDIR/veilid_wasm_bg.wasm -o $OUTPUTDIR/veilid_wasm_bg.wasm.map --dwarfdump $DWARFDUMP
|
./wasm-sourcemap.py $OUTPUTDIR/veilid_wasm_bg.wasm -o $OUTPUTDIR/veilid_wasm_bg.wasm.map --dwarfdump $DWARFDUMP
|
||||||
# wasm-strip $OUTPUTDIR/veilid_wasm_bg.wasm
|
# wasm-strip $OUTPUTDIR/veilid_wasm_bg.wasm
|
||||||
fi
|
fi
|
||||||
|
4
veilid-wasm/wasm_test.sh
Executable file
4
veilid-wasm/wasm_test.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
WASM_BINDGEN_USE_NO_MODULE=true wasm-pack test --firefox "$@"
|
Loading…
Reference in New Issue
Block a user