diff --git a/Cargo.lock b/Cargo.lock index 57fdce28..73def402 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -830,6 +830,7 @@ dependencies = [ "thiserror", "tokio", "tonic", + "tonic-web-wasm-client", "tower-http", "tracing", "tracing-subscriber", @@ -4330,6 +4331,30 @@ dependencies = [ "syn", ] +[[package]] +name = "tonic-web-wasm-client" +version = "0.5.1" +source = "git+https://github.com/devashishdxt/tonic-web-wasm-client.git#46b9051e60d6b0d73446ba01814af879a866ebc1" +dependencies = [ + "base64 0.22.1", + "byteorder", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "httparse", + "js-sys", + "pin-project", + "thiserror", + "tonic", + "tower-service", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + [[package]] name = "tower" version = "0.4.13" @@ -4729,6 +4754,19 @@ dependencies = [ "leb128", ] +[[package]] +name = "wasm-streams" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasmparser" version = "0.209.1" diff --git a/Cargo.toml b/Cargo.toml index 3197d9d3..d2006ee9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,8 @@ members = [ "rust/common-javascript-interpreter", "rust/common-macros", "rust/common-protos", - "rust/common-runtime", + # "rust/common-runtime", + "rust/common-runtime-experiment", "rust/common-test-fixtures", "rust/common-tracing", "rust/common-wit", @@ -28,7 +29,7 @@ common-builder = { path = "./rust/common-builder" } common-javascript-interpreter = { path = "./rust/common-javasript-interpreter" } common-macros = { path = "./rust/common-macros" } common-protos = { path = "./rust/common-protos", default-features = false } -common-runtime = { path = "./rust/common-runtime" } +common-runtime = { path = "./rust/common-runtime-experiment" } common-test-fixtures = { path = "./rust/common-test-fixtures" } common-tracing = { path = "./rust/common-tracing" } common-wit = { path = "./rust/common-wit" } @@ -56,9 +57,10 @@ sieve-cache = { version = "0.2" } syn = { version = "2" } tempfile = { version = "3" } thiserror = { version = "1" } +tokio = { version = "1" } tonic = { version = "0.12", default-features = false } tonic-build = { version = "0.12", default-features = false, features = [ "prost" ] } -tokio = { version = "1" } +tonic-web-wasm-client = { git = "https://github.com/devashishdxt/tonic-web-wasm-client.git" } tower-http = { version = "0.5" } tracing = { version = "0.1" } tracing-subscriber = { version = "0.3", features = ["env-filter", "tracing-log", "json"] } diff --git a/rust/common-javascript-interpreter/Cargo.toml b/rust/common-javascript-interpreter/Cargo.toml index 7b1c25c4..6cd9b3e0 100644 --- a/rust/common-javascript-interpreter/Cargo.toml +++ b/rust/common-javascript-interpreter/Cargo.toml @@ -25,11 +25,8 @@ common-test-fixtures = { workspace = true } crate-type = ["cdylib"] [package.metadata.component.target] -path = "wit/deps/script/script.wit" -world = "common" - -[package.metadata.component.target.dependencies."common:module"] -path = "wit/deps/module/module.wit" +path = "wit/deps/function/function.wit" +world = "virtual-module" [package.metadata.component.target.dependencies."common:data"] path = "wit/deps/data/data.wit" diff --git a/rust/common-javascript-interpreter/build.rs b/rust/common-javascript-interpreter/build.rs index 4dced5eb..685d4734 100644 --- a/rust/common-javascript-interpreter/build.rs +++ b/rust/common-javascript-interpreter/build.rs @@ -3,8 +3,7 @@ use std::process::Command; const TYPESCRIPT_SOURCE_DEPENDENCIES: &[&str] = &[ "common/io/wit/io.wit", "common/data/wit/data.wit", - "common/module/wit/module.wit", - "common/script/wit/script.wit", + "common/function/wit/function.wit", ]; fn main() { diff --git a/rust/common-javascript-interpreter/wit/deps.lock b/rust/common-javascript-interpreter/wit/deps.lock index 51348b2f..e76a28b5 100644 --- a/rust/common-javascript-interpreter/wit/deps.lock +++ b/rust/common-javascript-interpreter/wit/deps.lock @@ -6,12 +6,8 @@ sha512 = "aa6f16d180975d35dde3ebcd1b6a21992ee9e38ba9edf3f5535ff3415c3933792c8be5 sha256 = "3d6c8ae11439a90d1260d64030dc9ac003a72f2f7277df787b95c5a8f54d7474" sha512 = "87c77c5a22fdc2c9850ff9e6672f94a86c7c32a6f665d714caca5613f6bc2a1cca76d7ebb26ddf3bae80c32d5d692baab803aff61207aaaa87ffdbd8e6cdc109" -[module] -sha256 = "cc4b0b5358ef2f51743b26a09a4a81bca23cb647f0561691387d28bc48dbbd26" -sha512 = "7ff0a2fc4fa76decae57a3a8b8ee7f68c25c813eb1405e90e0c89a8045056b9cf5c1f3fa419845579cf920fd7e00f9c923b25664dc282dbff232a1dbd6e295d2" - [script] -path = "../../../typescript/common/script/wit" -sha256 = "a0eca742d07bf481984e31f05de30d89da0016b92a896bee3b83d6abada7ebf1" -sha512 = "f8849fd3c07f9e553c7909b90e53ee8a34c8f4a6982ebbb1fe2493e9f7db75d3d51f34e967794714903443abf9a6f180a74bfc555a4ac43c76832eba6ecd9aa6" -deps = ["data", "io", "module"] +path = "../../../typescript/common/function/wit" +sha256 = "4d2c15922d458487d376361c47a3dc62089540d2ebc0a1b2fc9e524c323d02b3" +sha512 = "a7d6f665016bdb9bbb72d3cbf533266cc5390a133056499e5a2a01896b93685f50144c547b2fcede78a01d1b92cce9d2666e5e30dce5a1dd6397a7b5a3f9abcc" +deps = ["data", "io"] diff --git a/rust/common-javascript-interpreter/wit/deps.toml b/rust/common-javascript-interpreter/wit/deps.toml index f9a2ede0..6714b270 100644 --- a/rust/common-javascript-interpreter/wit/deps.toml +++ b/rust/common-javascript-interpreter/wit/deps.toml @@ -1 +1 @@ -script = "../../../typescript/common/script/wit" \ No newline at end of file +script = "../../../typescript/common/function/wit" \ No newline at end of file diff --git a/rust/common-runtime-experiment/Cargo.toml b/rust/common-runtime-experiment/Cargo.toml new file mode 100644 index 00000000..e683711b --- /dev/null +++ b/rust/common-runtime-experiment/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "common-runtime" +description = "A Common runtime" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = { workspace = true } +async-trait = { workspace = true } +async-stream = { workspace = true } +blake3 = { workspace = true } +bytes = { workspace = true } +common-protos = { workspace = true, features = ["runtime", "builder"] } +common-tracing = { workspace = true } +common-wit = { workspace = true } +http = { workspace = true } +mime_guess = { workspace = true } +rand = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +sieve-cache = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +clap = { workspace = true, features = ["derive"] } +tokio = { workspace = true, features = ["rt-multi-thread", "io-util", "process", "fs"] } +tonic = { workspace = true, features = ["codegen", "prost", "transport"] } +tower-http = { workspace = true, features = ["cors"] } +wasmtime = { workspace = true } +wasmtime-wasi = { workspace = true } +wasmtime-wasi-http = { workspace = true } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { workspace = true, features = ["js"]} +tokio = { workspace = true, features = ["rt"] } +tonic = { workspace = true, features = ["codegen", "prost"] } +tonic-web-wasm-client = { workspace = true } + +[build-dependencies] +tempfile = { workspace = true } + +[dev-dependencies] +common-builder = { workspace = true } +common-test-fixtures = { workspace = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = { workspace = true, features = ["async_tokio"] } + +# [[bench]] +# name = "runtime_bench" +# harness = false +# required-features = ["bench"] diff --git a/rust/common-runtime-experiment/README.md b/rust/common-runtime-experiment/README.md new file mode 100644 index 00000000..1fb854ba --- /dev/null +++ b/rust/common-runtime-experiment/README.md @@ -0,0 +1,3 @@ +# common-runtime + +The Common Runtime is responsible for instantiating a Common Recipe and managing its lifecycle. diff --git a/rust/common-runtime-experiment/src/content_type.rs b/rust/common-runtime-experiment/src/content_type.rs new file mode 100644 index 00000000..4d4779b2 --- /dev/null +++ b/rust/common-runtime-experiment/src/content_type.rs @@ -0,0 +1,28 @@ +use common_protos::common; + +/// Supported content types that may be embodied as a [crate::CommonModule] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ContentType { + /// JavaScript or TypeScript code + JavaScript, + /// Python code + Python, +} + +impl From for ContentType { + fn from(value: common::ContentType) -> Self { + match value { + common::ContentType::JavaScript => ContentType::JavaScript, + common::ContentType::Python => ContentType::Python, + } + } +} + +impl From for common::ContentType { + fn from(value: ContentType) -> Self { + match value { + ContentType::JavaScript => common::ContentType::JavaScript, + ContentType::Python => common::ContentType::Python, + } + } +} diff --git a/rust/common-runtime-experiment/src/error.rs b/rust/common-runtime-experiment/src/error.rs new file mode 100644 index 00000000..8da23614 --- /dev/null +++ b/rust/common-runtime-experiment/src/error.rs @@ -0,0 +1,68 @@ +use std::fmt::Debug; +use thiserror::Error; + +use crate::ModuleInstanceId; + +/// Various errors that may be encountered when invoking runtime code. +#[derive(Error, Debug)] +pub enum CommonRuntimeError { + /// A Wasm Component failed to prepare + #[error("Failed to prepare a Wasm Component: {0}")] + PreparationFailed(String), + + /// A Wasm Component failed to link + #[error("Failed to link a Wasm Component: {0}")] + LinkFailed(String), + + /// A sandbox failed to be created + #[error("Failed to instantiate a sandbox: {0}")] + SandboxCreationFailed(String), + + /// A Common Module failed to be instantiated + #[error("Failed to instantiate a Common Module: {0}")] + ModuleInstantiationFailed(String), + + /// An error occurred when a Common Module was run + #[error("Failed to run a Common Module: {0}")] + ModuleRunFailed(String), + + /// An unexpected internal error occurred + #[error("Internal error")] + InternalError(String), + + /// A specified Common Module ID was not valid + #[error("Invalid Common Module ID: {0}")] + InvalidModuleId(String), + + /// The configured target was missing or invalid + #[error("Invalid Common Module Target: {0}")] + InvalidModuleTarget(String), + + /// The configured target was missing or invalid + #[error("Invalid Common Module Affinity: {0}")] + InvalidModuleAffinity(String), + + /// The specified Common Module instance ID did not correspond to a living + /// instance + #[error("Unknown Common Module instance ID: {0}")] + UnknownInstanceId(ModuleInstanceId), + + /// A provided Value was empty or of an unexpected shape + #[error("Invalid Value")] + InvalidValue, + + /// The provided module sources were missing or otherwise invalid + #[error("Invalid module source: {0}")] + InvalidModuleSource(String), + + /// The provided instantiation parameters are not supported + #[error("Invalid instantiation parameters: {0}")] + InvalidInstantiationParameters(String), +} + +#[cfg(not(target_arch = "wasm32"))] +impl From for CommonRuntimeError { + fn from(value: tonic::transport::Error) -> Self { + CommonRuntimeError::InternalError(format!("{value}")) + } +} diff --git a/rust/common-runtime-experiment/src/io.rs b/rust/common-runtime-experiment/src/io.rs new file mode 100644 index 00000000..a0bfe7ed --- /dev/null +++ b/rust/common-runtime-experiment/src/io.rs @@ -0,0 +1,55 @@ +use std::collections::BTreeMap; + +use crate::{sync::ConditionalSync, Value, ValueKind}; + +/// A convenience alias for the expected shape of Common Module outputs +pub type Output = BTreeMap; + +/// A convenience alias for the expected shape of Common Module output shapes +pub type OutputShape = BTreeMap; + +/// A generic trait for a reference to state. The implementation may embody +/// state that is opaque, readable and/or writable. +pub trait InputOutput: Clone + Default + ConditionalSync + std::fmt::Debug { + /// Attempt to read some [Value] from state that is assigned some well-known + /// `key`. A value may be returned if it is part of the state, and the reader + /// is allowed to read it. + fn read(&self, key: &str) -> Option; + + /// Write some [Value] to a well-known `key`. The write may or may not be + /// accepted. There is no prescription made as to the transactional + /// guarantees of a call to `write`. Subsequent calls to `read` for the same + /// `key` may or may not reflect the effect of a `write`, regardless of + /// whether or not it was considered to be successful. + fn write(&mut self, key: &str, value: Value); + + /// Get a mapping of the output keys to their set values. Keys with no set + /// values will not be pressent in the output, even if they were allowed to + /// be set. + fn output(&self) -> &Output; + + /// Get the shape of the output, which is the expected [ValueKind] that maps + /// to each allowed key in the output space + fn output_shape(&self) -> &OutputShape; +} + +impl InputOutput for Box +where + Io: InputOutput, +{ + fn read(&self, key: &str) -> Option { + self.as_ref().read(key) + } + + fn write(&mut self, key: &str, value: Value) { + self.as_mut().write(key, value) + } + + fn output(&self) -> &Output { + self.as_ref().output() + } + + fn output_shape(&self) -> &OutputShape { + self.as_ref().output_shape() + } +} diff --git a/rust/common-runtime-experiment/src/lib.rs b/rust/common-runtime-experiment/src/lib.rs new file mode 100644 index 00000000..2432437b --- /dev/null +++ b/rust/common-runtime-experiment/src/lib.rs @@ -0,0 +1,19 @@ +mod module; +pub use module::*; + +mod error; +pub use error::*; + +mod content_type; +pub use content_type::*; + +mod value; +pub use value::*; + +mod sync; +pub use sync::*; + +mod io; +pub use io::*; + +pub mod runtime; diff --git a/rust/common-runtime-experiment/src/module/affinity.rs b/rust/common-runtime-experiment/src/module/affinity.rs new file mode 100644 index 00000000..c93779c2 --- /dev/null +++ b/rust/common-runtime-experiment/src/module/affinity.rs @@ -0,0 +1,7 @@ +pub struct LocalOnly; + +pub struct RemoteOnly; + +pub struct PrefersLocal; + +pub struct PrefersRemote; diff --git a/rust/common-runtime-experiment/src/module/body.rs b/rust/common-runtime-experiment/src/module/body.rs new file mode 100644 index 00000000..7e7f743e --- /dev/null +++ b/rust/common-runtime-experiment/src/module/body.rs @@ -0,0 +1,6 @@ +use super::{ModuleId, SourceCodeCollection}; + +pub enum ModuleBody { + Id(ModuleId), + SourceCode(SourceCodeCollection), +} diff --git a/rust/common-runtime-experiment/src/module/builder.rs b/rust/common-runtime-experiment/src/module/builder.rs new file mode 100644 index 00000000..cef850b4 --- /dev/null +++ b/rust/common-runtime-experiment/src/module/builder.rs @@ -0,0 +1,83 @@ +use crate::{CommonRuntimeError, ValueKind}; + +use super::{Module, ModuleBody, ModuleId, ModuleIoShape, SourceCode, SourceCodeCollection}; + +#[derive(Default)] +pub struct ModuleBuilder +where + Target: Into, +{ + target: Option, + affinity: Option, + + module_id: Option, + module_sources: SourceCodeCollection, + io_shape: ModuleIoShape, +} + +impl ModuleBuilder +where + Target: Into, +{ + pub fn target(mut self, target: Target) -> Self { + self.target = Some(target); + self + } + + pub fn affinity(mut self, affinity: Affinity) -> Self { + self.affinity = Some(affinity); + self + } + + pub fn input(mut self, key: String, value: ValueKind) -> Self { + self.io_shape.input.insert(key, value); + self + } + + pub fn output(mut self, key: String, value: ValueKind) -> Self { + self.io_shape.output.insert(key, value); + self + } + + pub fn source_code(mut self, name: String, source_code: SourceCode) -> Self { + self.module_sources.insert(name, source_code); + self + } + + pub fn build(self) -> Result, CommonRuntimeError> { + let body = if let Some(id) = self.module_id { + ModuleBody::Id(id.clone()) + } else if !self.module_sources.is_empty() { + ModuleBody::SourceCode(self.module_sources) + } else { + return Err(CommonRuntimeError::InvalidModuleSource( + "Either a Module ID or at least one input source file must be provided".into(), + )); + }; + + let target = if let Some(target) = self.target { + target + } else { + return Err(CommonRuntimeError::InvalidModuleTarget( + "A Target was not configured for the Common Module".into(), + )); + }; + + let affinity = if let Some(affinity) = self.affinity { + affinity + } else { + return Err(CommonRuntimeError::InvalidModuleAffinity( + "An Affinity was not configured for the Common Module".into(), + )); + }; + + let io_shape = self.io_shape; + + Ok(Module { + target, + affinity, + body, + io_shape, + }) + } +} diff --git a/rust/common-runtime-experiment/src/module/definition.rs b/rust/common-runtime-experiment/src/module/definition.rs new file mode 100644 index 00000000..78527532 --- /dev/null +++ b/rust/common-runtime-experiment/src/module/definition.rs @@ -0,0 +1,12 @@ +use super::{ModuleBody, ModuleIoShape}; + +pub struct Module +where + Target: Into, +{ + pub target: Target, + pub affinity: Affinity, + + pub body: ModuleBody, + pub io_shape: ModuleIoShape, +} diff --git a/rust/common-runtime-experiment/src/module/id.rs b/rust/common-runtime-experiment/src/module/id.rs new file mode 100644 index 00000000..c8df8471 --- /dev/null +++ b/rust/common-runtime-experiment/src/module/id.rs @@ -0,0 +1,105 @@ +use std::{fmt::Display, str::FromStr}; + +use crate::CommonRuntimeError; + +/// A unique instance ID that may be used to identify an instantiation of an +/// given module. +/// +/// TODO: Would be nice to say that an instance ID was derived from a module ID +#[repr(transparent)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ModuleInstanceId(pub String); + +impl Display for ModuleInstanceId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +/// A [ModuleId] uniquely identifies a given Common Module. At this time it is +/// always expected to represent the hash of the Common Module's Wasm Component +/// artifact. +/// +/// TODO: This needs a definition that supports interpreted mode. Hash of +/// sources, perhaps? +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub enum ModuleId { + /// The [ModuleId] is in the form of [blake3::Hash] bytes. + Hash(blake3::Hash), + /// The [ModuleId] is a base64-encoded string + Base64(String), +} + +impl From for ModuleId { + fn from(value: String) -> Self { + ModuleId::Base64(value) + } +} + +impl From for ModuleId { + fn from(value: blake3::Hash) -> Self { + ModuleId::Hash(value) + } +} + +impl TryFrom for blake3::Hash { + type Error = CommonRuntimeError; + + fn try_from(value: ModuleId) -> Result { + Ok(match value { + ModuleId::Hash(hash) => hash, + ModuleId::Base64(string) => blake3::Hash::from_str(&string) + .map_err(|error| CommonRuntimeError::InvalidModuleId(format!("{error}")))?, + }) + } +} + +impl TryFrom for ModuleInstanceId { + type Error = CommonRuntimeError; + + fn try_from(value: ModuleId) -> Result { + let millis = std::time::SystemTime::now() + .elapsed() + .map_err(|error| CommonRuntimeError::InternalError(format!("{error}")))? + .as_millis(); + + let entropy = rand::random::(); + let hash = blake3::Hash::try_from(value)?; + let mut hasher = blake3::Hasher::new_keyed(hash.as_bytes()); + + Ok(ModuleInstanceId( + hasher + .update( + &millis + .to_le_bytes() + .into_iter() + .chain(entropy.to_le_bytes()) + .collect::>(), + ) + .finalize() + .to_string(), + )) + } +} + +impl ModuleId { + /// Convert the [ModuleId] to raw bytes corresponding to the [blake3::Hash] + pub fn to_bytes(&self) -> Result, CommonRuntimeError> { + Ok(match self { + ModuleId::Hash(hash) => hash.as_bytes().to_vec(), + ModuleId::Base64(string) => blake3::Hash::from_str(string) + .map_err(|error| CommonRuntimeError::InvalidModuleId(format!("{error}")))? + .as_bytes() + .to_vec(), + }) + } +} + +impl Display for ModuleId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ModuleId::Hash(hash) => write!(f, "{}", hash), + ModuleId::Base64(string) => write!(f, "{string}"), + } + } +} diff --git a/rust/common-runtime-experiment/src/module/instance/function.rs b/rust/common-runtime-experiment/src/module/instance/function.rs new file mode 100644 index 00000000..25361c92 --- /dev/null +++ b/rust/common-runtime-experiment/src/module/instance/function.rs @@ -0,0 +1,20 @@ +mod remote; +pub use remote::*; + +mod local; +pub use local::*; + +use async_trait::async_trait; + +use crate::CommonRuntimeError; + +use super::{ModuleInstance, Runtime}; + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +pub trait FunctionInstance: ModuleInstance +where + R: Runtime, +{ + async fn run(&self, io: R::InputOutput) -> Result; +} diff --git a/rust/common-runtime-experiment/src/module/instance/function/local.rs b/rust/common-runtime-experiment/src/module/instance/function/local.rs new file mode 100644 index 00000000..f8b385b4 --- /dev/null +++ b/rust/common-runtime-experiment/src/module/instance/function/local.rs @@ -0,0 +1,47 @@ +use std::marker::PhantomData; + +use super::FunctionInstance; +use crate::{CommonRuntimeError, InputOutput, ModuleInstance, ModuleInstanceId, Runtime}; +use async_trait::async_trait; + +pub struct LocalFunction +where + Rt: Runtime, +{ + id: ModuleInstanceId, + io: Rt::InputOutput, +} + +impl ModuleInstance for LocalFunction +where + Rt: Runtime, +{ + fn id(&self) -> &ModuleInstanceId { + &self.id + } + + fn io(&self) -> &::InputOutput { + &self.io + } +} + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +impl FunctionInstance for LocalFunction +where + Rt: Runtime, +{ + async fn run(&self) -> Result<(), CommonRuntimeError> { + todo!() + } +} + +pub struct LocalFunctionVm {} + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +impl FunctionInstance for LocalFunctionVm { + async fn run(&self) -> Result<(), CommonRuntimeError> { + todo!() + } +} diff --git a/rust/common-runtime-experiment/src/module/instance/function/remote.rs b/rust/common-runtime-experiment/src/module/instance/function/remote.rs new file mode 100644 index 00000000..e462bebd --- /dev/null +++ b/rust/common-runtime-experiment/src/module/instance/function/remote.rs @@ -0,0 +1,24 @@ +use super::FunctionInstance; +use crate::CommonRuntimeError; + +use async_trait::async_trait; + +pub struct RemoteFunction {} + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +impl FunctionInstance for RemoteFunction { + async fn run(&self) -> Result<(), CommonRuntimeError> { + todo!() + } +} + +pub struct RemoteFunctionVm {} + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +impl FunctionInstance for RemoteFunctionVm { + async fn run(&self) -> Result<(), CommonRuntimeError> { + todo!() + } +} diff --git a/rust/common-runtime-experiment/src/module/instance/instantiable.rs b/rust/common-runtime-experiment/src/module/instance/instantiable.rs new file mode 100644 index 00000000..f0e07e9b --- /dev/null +++ b/rust/common-runtime-experiment/src/module/instance/instantiable.rs @@ -0,0 +1,23 @@ +use crate::CommonRuntimeError; +use async_trait::async_trait; + +use super::{ModuleInstance, Runtime}; + +mod local_function; +mod local_function_vm; +mod remote_function; +mod remote_function_vm; + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +pub trait Instantiable +where + Rt: Runtime, +{ + type ModuleInstance: ModuleInstance; + + async fn instantiate( + &mut self, + runtime: Rt, + ) -> Result; +} diff --git a/rust/common-runtime-experiment/src/module/instance/instantiable/local_function.rs b/rust/common-runtime-experiment/src/module/instance/instantiable/local_function.rs new file mode 100644 index 00000000..0f914258 --- /dev/null +++ b/rust/common-runtime-experiment/src/module/instance/instantiable/local_function.rs @@ -0,0 +1,42 @@ +use async_trait::async_trait; + +use crate::{ + affinity::LocalOnly, + runtime::feature::{LocalInstantiation, NativeMachine}, + target::CommonFunction, + CommonRuntimeError, LocalFunction, Module, Runtime, +}; + +use super::Instantiable; + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +impl Instantiable for Module +where + Rt: Runtime + LocalInstantiation + NativeMachine + 'static, +{ + type ModuleInstance = LocalFunction; + + async fn instantiate( + &mut self, + runtime: Rt, + ) -> Result { + todo!() + } +} + +// #[cfg_attr(not(target_arch = "wasm32"), async_trait)] +// #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +// impl Instantiable for Module +// where +// R: LocalInstantiation + NativeMachine, +// { +// type ModuleInstance = LocalFunction; + +// async fn instantiate( +// &mut self, +// runtime: R, +// ) -> Result { +// todo!() +// } +// } diff --git a/rust/common-runtime-experiment/src/module/instance/instantiable/local_function_vm.rs b/rust/common-runtime-experiment/src/module/instance/instantiable/local_function_vm.rs new file mode 100644 index 00000000..e69de29b diff --git a/rust/common-runtime-experiment/src/module/instance/instantiable/remote_function.rs b/rust/common-runtime-experiment/src/module/instance/instantiable/remote_function.rs new file mode 100644 index 00000000..e69de29b diff --git a/rust/common-runtime-experiment/src/module/instance/instantiable/remote_function_vm.rs b/rust/common-runtime-experiment/src/module/instance/instantiable/remote_function_vm.rs new file mode 100644 index 00000000..e69de29b diff --git a/rust/common-runtime-experiment/src/module/instance/mod.rs b/rust/common-runtime-experiment/src/module/instance/mod.rs new file mode 100644 index 00000000..9c526bae --- /dev/null +++ b/rust/common-runtime-experiment/src/module/instance/mod.rs @@ -0,0 +1,36 @@ +mod instantiable; +pub use instantiable::*; + +mod function; +pub use function::*; + +use super::ModuleInstanceId; +use crate::{ConditionalSync, InputOutput}; + +pub trait Runtime { + type InputOutput: InputOutput; +} + +/// A [ModuleInstance] represents a live instantiation of a Common Module. The +/// Common Module's `run` implementation may be invoked, allowing it to perform +/// some changes to a provided [InputOutput]. +pub trait ModuleInstance: ConditionalSync +where + Rt: Runtime, +{ + /// The uniquely-identifying ID of this [ModuleInstance] + fn id(&self) -> &ModuleInstanceId; + + fn io(&self) -> &Rt::InputOutput; +} + +// impl ModuleInstance for Box +// where +// T: ModuleInstance, +// { +// type InputOutput = T::InputOutput; + +// fn id(&self) -> &ModuleInstanceId { +// T::id(self) +// } +// } diff --git a/rust/common-runtime-experiment/src/module/io.rs b/rust/common-runtime-experiment/src/module/io.rs new file mode 100644 index 00000000..84de98ff --- /dev/null +++ b/rust/common-runtime-experiment/src/module/io.rs @@ -0,0 +1,9 @@ +use std::collections::BTreeMap; + +use crate::ValueKind; + +#[derive(Default)] +pub struct ModuleIoShape { + pub input: BTreeMap, + pub output: BTreeMap, +} diff --git a/rust/common-runtime-experiment/src/module/mod.rs b/rust/common-runtime-experiment/src/module/mod.rs new file mode 100644 index 00000000..197cd21c --- /dev/null +++ b/rust/common-runtime-experiment/src/module/mod.rs @@ -0,0 +1,29 @@ +mod builder; +pub use builder::*; + +mod id; +pub use id::*; + +mod body; +pub use body::*; + +mod source; +pub use source::*; + +mod signature; +pub use signature::*; + +mod instance; +pub use instance::*; + +mod definition; +pub use definition::*; + +mod io; +pub use io::*; + +mod prepared; +pub use prepared::*; + +pub mod affinity; +pub mod target; diff --git a/rust/common-runtime-experiment/src/module/prepared.rs b/rust/common-runtime-experiment/src/module/prepared.rs new file mode 100644 index 00000000..e1b56daa --- /dev/null +++ b/rust/common-runtime-experiment/src/module/prepared.rs @@ -0,0 +1,43 @@ +use crate::{CommonRuntimeError, ConditionalSync, InputOutput}; + +use async_trait::async_trait; + +use super::ModuleInstance; + +/// A [PreparedModule] is a [crate::Module] that is ready to be instantiated. For example, +/// an underlying Wasm Component may be compiled but not yet instanced. +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +pub trait PreparedModule: Clone + ConditionalSync { + /// An implementation of [InputOutput] that will be used to provide + /// state to the instantiated module + type InputOutput: InputOutput; + + /// The shape of the module after instantiation + type ModuleInstance: ModuleInstance; + + /// Instantiate the [PreparedModule], using the provided [InputOutput] as + /// the "default" state shared with the module instance. + async fn instantiate( + &self, + io: Self::InputOutput, + ) -> Result; +} + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +impl PreparedModule for std::sync::Arc +where + T: PreparedModule, +{ + type InputOutput = T::InputOutput; + + type ModuleInstance = T::ModuleInstance; + + async fn instantiate( + &self, + io: Self::InputOutput, + ) -> Result { + T::instantiate(self, io).await + } +} diff --git a/rust/common-runtime-experiment/src/module/signature.rs b/rust/common-runtime-experiment/src/module/signature.rs new file mode 100644 index 00000000..fdaa2139 --- /dev/null +++ b/rust/common-runtime-experiment/src/module/signature.rs @@ -0,0 +1,7 @@ +use super::ModuleId; +use common_wit::Target; + +pub struct ModuleSignature { + pub target: Target, + pub id: ModuleId, +} diff --git a/rust/common-runtime-experiment/src/module/source.rs b/rust/common-runtime-experiment/src/module/source.rs new file mode 100644 index 00000000..ebad544d --- /dev/null +++ b/rust/common-runtime-experiment/src/module/source.rs @@ -0,0 +1,14 @@ +use crate::ContentType; +use bytes::Bytes; +use std::collections::BTreeMap; + +/// A pairing of raw source code bytes and an associated [ContentType] +#[derive(Debug, Clone)] +pub struct SourceCode { + /// The mime of the source + pub content_type: ContentType, + /// The raw bytes of the source + pub body: Bytes, +} + +pub type SourceCodeCollection = BTreeMap; diff --git a/rust/common-runtime-experiment/src/module/target.rs b/rust/common-runtime-experiment/src/module/target.rs new file mode 100644 index 00000000..17d9bd9e --- /dev/null +++ b/rust/common-runtime-experiment/src/module/target.rs @@ -0,0 +1,15 @@ +pub struct CommonFunction; + +impl From for common_wit::Target { + fn from(_: CommonFunction) -> Self { + common_wit::Target::CommonFunction + } +} + +pub struct CommonFunctionVm; + +impl From for common_wit::Target { + fn from(_: CommonFunctionVm) -> Self { + common_wit::Target::CommonFunctionVm + } +} diff --git a/rust/common-runtime-experiment/src/runtime/feature.rs b/rust/common-runtime-experiment/src/runtime/feature.rs new file mode 100644 index 00000000..61fb64f4 --- /dev/null +++ b/rust/common-runtime-experiment/src/runtime/feature.rs @@ -0,0 +1,34 @@ +use common_wit::Target; + +use crate::{InputOutput, ModuleBody, ModuleInstance, PreparedModule, Runtime}; +use async_trait::async_trait; + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +pub trait NativeMachine { + type PreparedModule: PreparedModule; + + async fn prepare_compiled_module( + &mut self, + target: Target, + body: ModuleBody, + ) -> Self::PreparedModule; +} + +pub trait VirtualMachine {} + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +pub trait LocalInstantiation +where + Rt: Runtime, +{ + type InputOutput: InputOutput; + type ModuleInstance: ModuleInstance; + + async fn instantiate_local_module

(&mut self, prepared_module: P) -> Self::ModuleInstance + where + P: PreparedModule; +} + +pub trait RemoteInstantiation {} diff --git a/rust/common-runtime-experiment/src/runtime/local/mod.rs b/rust/common-runtime-experiment/src/runtime/local/mod.rs new file mode 100644 index 00000000..3d828892 --- /dev/null +++ b/rust/common-runtime-experiment/src/runtime/local/mod.rs @@ -0,0 +1 @@ +pub mod wasmtime; diff --git a/rust/common-runtime-experiment/src/runtime/local/wasmtime/mod.rs b/rust/common-runtime-experiment/src/runtime/local/wasmtime/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/rust/common-runtime-experiment/src/runtime/local/wasmtime/mod.rs @@ -0,0 +1 @@ + diff --git a/rust/common-runtime-experiment/src/runtime/mod.rs b/rust/common-runtime-experiment/src/runtime/mod.rs new file mode 100644 index 00000000..cf4aaacc --- /dev/null +++ b/rust/common-runtime-experiment/src/runtime/mod.rs @@ -0,0 +1,3 @@ +pub mod local; + +pub mod feature; diff --git a/rust/common-runtime-experiment/src/sync.rs b/rust/common-runtime-experiment/src/sync.rs new file mode 100644 index 00000000..2f3145c7 --- /dev/null +++ b/rust/common-runtime-experiment/src/sync.rs @@ -0,0 +1,31 @@ +//! The traits herein are intended for use as a compatiblity mechanism for async +//! code that may target both `wasm32-unknown-unknown` as well as native targets +//! where the implementor may be shared across threads. + +#[allow(missing_docs)] +#[cfg(not(target_arch = "wasm32"))] +pub trait ConditionalSend: Send {} + +#[cfg(not(target_arch = "wasm32"))] +impl ConditionalSend for S where S: Send {} + +#[allow(missing_docs)] +#[cfg(not(target_arch = "wasm32"))] +pub trait ConditionalSync: Send + Sync {} + +#[cfg(not(target_arch = "wasm32"))] +impl ConditionalSync for S where S: Send + Sync {} + +#[allow(missing_docs)] +#[cfg(target_arch = "wasm32")] +pub trait ConditionalSend {} + +#[cfg(target_arch = "wasm32")] +impl ConditionalSend for S {} + +#[allow(missing_docs)] +#[cfg(target_arch = "wasm32")] +pub trait ConditionalSync {} + +#[cfg(target_arch = "wasm32")] +impl ConditionalSync for S {} diff --git a/rust/common-runtime-experiment/src/value.rs b/rust/common-runtime-experiment/src/value.rs new file mode 100644 index 00000000..83e401d6 --- /dev/null +++ b/rust/common-runtime-experiment/src/value.rs @@ -0,0 +1,79 @@ +use crate::CommonRuntimeError; +use common_protos::common; + +/// An intrinsic value type within a Common Runtime +#[derive(Clone, Debug)] +pub enum Value { + /// A UTF-8 string + String(String), + /// A boolean: true or false + Boolean(bool), + /// A double-precision floating-point number + Number(f64), + /// A slab of bytes + Buffer(Vec), +} + +impl Value { + /// Check if a [ValueKind] corresponds to the type of this [Value] + pub fn is_of_kind(&self, kind: &ValueKind) -> bool { + match self { + Value::String(_) if kind == &ValueKind::String => true, + Value::Boolean(_) if kind == &ValueKind::Boolean => true, + Value::Number(_) if kind == &ValueKind::Number => true, + Value::Buffer(_) if kind == &ValueKind::Buffer => true, + _ => false, + } + } +} + +/// The set of variant types for [Value] +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum ValueKind { + /// A UTF-8 string + String, + /// A boolean: true or false + Boolean, + /// A double-precision floating-point number + Number, + /// A slab of bytes + Buffer, +} + +impl TryFrom for Value { + type Error = CommonRuntimeError; + + fn try_from(value: common::Value) -> Result { + let value = value.variant.ok_or(CommonRuntimeError::InvalidValue)?; + Ok(match value { + common::value::Variant::String(string) => Value::String(string), + common::value::Variant::Number(number) => Value::Number(number), + common::value::Variant::Boolean(boolean) => Value::Boolean(boolean), + common::value::Variant::Buffer(buffer) => Value::Buffer(buffer), + }) + } +} + +impl From for common::Value { + fn from(value: Value) -> Self { + common::Value { + variant: Some(match value { + Value::String(string) => common::value::Variant::String(string), + Value::Boolean(number) => common::value::Variant::Boolean(number), + Value::Number(boolean) => common::value::Variant::Number(boolean), + Value::Buffer(buffer) => common::value::Variant::Buffer(buffer), + }), + } + } +} + +impl From for ValueKind { + fn from(value_kind: common::ValueKind) -> Self { + match value_kind { + common::ValueKind::String => ValueKind::String, + common::ValueKind::Boolean => ValueKind::Boolean, + common::ValueKind::Number => ValueKind::Number, + common::ValueKind::Buffer => ValueKind::Buffer, + } + } +} diff --git a/rust/common-runtime/Cargo.toml b/rust/common-runtime/Cargo.toml index 24665ca8..635bfe28 100644 --- a/rust/common-runtime/Cargo.toml +++ b/rust/common-runtime/Cargo.toml @@ -36,6 +36,7 @@ wasmtime-wasi-http = { workspace = true } getrandom = { workspace = true, features = ["js"]} tokio = { workspace = true, features = ["rt"] } tonic = { workspace = true, features = ["codegen", "prost"] } +tonic-web-wasm-client = { workspace = true } [build-dependencies] tempfile = { workspace = true } diff --git a/rust/common-runtime/src/lib.rs b/rust/common-runtime/src/lib.rs index b71a456e..afa05c08 100644 --- a/rust/common-runtime/src/lib.rs +++ b/rust/common-runtime/src/lib.rs @@ -11,8 +11,9 @@ extern crate tracing; mod components; pub use components::*; -mod sandbox; -pub use sandbox::*; +pub mod sandbox; + +pub mod runtime_experiment; mod error; pub use error::*; @@ -20,6 +21,9 @@ pub use error::*; mod content_type; pub use content_type::*; +mod schedule; +pub use schedule::*; + mod value; pub use value::*; @@ -34,7 +38,6 @@ pub use serve::*; mod io; pub use io::*; -mod runtime; -pub use runtime::*; +pub mod runtime; pub mod sync; diff --git a/rust/common-runtime/src/module/raw.rs b/rust/common-runtime/src/module/raw.rs index dc1552ee..cd28a42d 100644 --- a/rust/common-runtime/src/module/raw.rs +++ b/rust/common-runtime/src/module/raw.rs @@ -51,7 +51,7 @@ impl RawModule { #[cfg(not(target_arch = "wasm32"))] async fn wasm(&self) -> Result<(ModuleId, Bytes), CommonRuntimeError> { match self.module_source.target { - Target::CommonModule => { + Target::CommonFunction => { let (id, bytes) = self .wasm .get_or_try_init(|| async { @@ -91,7 +91,7 @@ impl RawModule { .await?; Ok((id.clone(), bytes.clone())) } - Target::CommonScript => { + Target::CommonFunctionVm => { let (_, entrypoint) = self.module_source.entrypoint()?; match entrypoint.content_type { ContentType::JavaScript => { diff --git a/rust/common-runtime/src/module/source.rs b/rust/common-runtime/src/module/source.rs index 3e3a5c80..b95b08e6 100644 --- a/rust/common-runtime/src/module/source.rs +++ b/rust/common-runtime/src/module/source.rs @@ -4,6 +4,27 @@ use common_protos::common; use common_wit::Target; use std::collections::BTreeMap; +use super::ModuleId; + +pub struct ModuleSignature { + pub target: Target, + pub id: ModuleId, +} + +pub enum ModuleReference { + Signature(ModuleSignature), + Source(ModuleSource), +} + +impl ModuleReference { + pub fn target(&self) -> &Target { + match self { + ModuleReference::Signature(signature) => &signature.target, + ModuleReference::Source(source) => &source.target, + } + } +} + /// A structured collection of source inputs needed to build a module with the given [WitTarget]. #[derive(Debug, Clone)] pub struct ModuleSource { @@ -44,8 +65,8 @@ impl From for ModuleSource { fn from(value: common::ModuleSource) -> Self { ModuleSource { target: match value.target() { - common::Target::CommonModule => Target::CommonModule, - common::Target::CommonScript => Target::CommonScript, + common::Target::CommonModule => Target::CommonFunction, + common::Target::CommonScript => Target::CommonFunctionVm, }, source_code: value .source_code @@ -60,8 +81,8 @@ impl From for common::ModuleSource { fn from(value: ModuleSource) -> Self { common::ModuleSource { target: match value.target { - Target::CommonModule => common::Target::CommonModule.into(), - Target::CommonScript => common::Target::CommonScript.into(), + Target::CommonFunction => common::Target::CommonModule.into(), + Target::CommonFunctionVm => common::Target::CommonScript.into(), }, source_code: value .source_code diff --git a/rust/common-runtime/src/runtime/browser/mod.rs b/rust/common-runtime/src/runtime/browser/mod.rs new file mode 100644 index 00000000..192fbeaa --- /dev/null +++ b/rust/common-runtime/src/runtime/browser/mod.rs @@ -0,0 +1,2 @@ +mod remote; +pub use remote::*; diff --git a/rust/common-runtime/src/runtime/browser/remote.rs b/rust/common-runtime/src/runtime/browser/remote.rs new file mode 100644 index 00000000..cc985131 --- /dev/null +++ b/rust/common-runtime/src/runtime/browser/remote.rs @@ -0,0 +1,75 @@ +use std::{cell::RefCell, collections::BTreeMap, rc::Rc}; + +use common_protos::{ + common, + runtime::{self, runtime_client::RuntimeClient}, +}; +use common_wit::Target; +use http::Uri; +use tonic_web_wasm_client::Client; + +use crate::{ + runtime::RuntimeIo, CommonRuntimeError, ModuleDefinition, ModuleInstanceId, ModuleSource, + ToModuleSources, ToWasmComponent, +}; + +// TODO: Support `RemoteRuntime` use in non-`wasm32-unknown-unknown` cases + +#[derive(Clone)] +pub struct RemoteRuntime { + client: RefCell>, + module_instances: BTreeMap, +} + +impl RemoteRuntime { + pub fn new(address: Uri) -> Self { + let client = RefCell::new(RuntimeClient::new(Client::new(address.to_string()))); + // RemoteRuntime { client } + + todo!(); + } + + pub async fn interpret< + Module: ModuleDefinition + ToModuleSources + ToWasmComponent + 'static, + >( + &mut self, + module: Module, + io: RuntimeIo, + ) -> Result { + let mut client = self.client.get_mut(); + + let module_source = ModuleSource { + target: Target::CommonFunctionVm, + source_code: module.to_module_sources().await?.ok_or_else(|| { + CommonRuntimeError::InvalidInstantiationParameters("No source code provided".into()) + })?, + }; + + let response = client + .instantiate_module(runtime::InstantiateModuleRequest { + output_shape: [("bar".into(), common::ValueKind::String.into())].into(), + default_input: [( + "foo".into(), + common::Value { + variant: Some(common::value::Variant::String("initial foo".into())), + }, + )] + .into(), + module_reference: Some( + runtime::instantiate_module_request::ModuleReference::ModuleSource( + module_source.into(), + ), + ), + }) + .await + .map_err(|error| { + CommonRuntimeError::ModuleInstantiationFailed(format!( + "Remote runtime status: {}", + error + )) + })? + .into_inner(); + + Ok(ModuleInstanceId(response.instance_id)) + } +} diff --git a/rust/common-runtime/src/runtime/io.rs b/rust/common-runtime/src/runtime/io.rs new file mode 100644 index 00000000..ea6a6c82 --- /dev/null +++ b/rust/common-runtime/src/runtime/io.rs @@ -0,0 +1,74 @@ +use common_protos::common; + +use crate::{CommonRuntimeError, InputOutput, OutputShape, Value, ValueKind}; +use std::collections::{BTreeMap, HashMap}; + +/// An implementation of [InputOutput] that is suitable for use with a +/// [Runtime]. +#[derive(Debug, Default, Clone)] +pub struct RuntimeIo { + input: BTreeMap, + output_shape: BTreeMap, + output: BTreeMap, +} + +impl RuntimeIo { + /// Instantiate a [RuntimeIo], providing initial input state, and the + /// expected shape of output state. + pub fn new(input: BTreeMap, output_shape: BTreeMap) -> Self { + Self { + input, + output_shape, + output: BTreeMap::new(), + } + } +} + +impl InputOutput for RuntimeIo { + fn read(&self, key: &str) -> Option { + self.input.get(key).cloned() + } + + fn write(&mut self, key: &str, value: Value) { + if let Some(kind) = self.output_shape.get(key) { + if value.is_of_kind(kind) { + self.output.insert(key.into(), value); + } else { + warn!("Ignoring write with unexpected shape to '{key}'"); + } + } else { + warn!("Ignoring write to unexpected output key '{key}'"); + } + } + + fn output(&self) -> &BTreeMap { + &self.output + } + + fn output_shape(&self) -> &OutputShape { + &self.output_shape + } +} + +impl TryFrom<(HashMap, HashMap)> for RuntimeIo { + type Error = CommonRuntimeError; + + fn try_from( + (input_proto, output_shape_proto): (HashMap, HashMap), + ) -> Result { + let mut input = BTreeMap::new(); + for (key, value) in input_proto.into_iter() { + input.insert(key, Value::try_from(value)?); + } + + let mut output_shape = BTreeMap::new(); + + for (key, value_kind) in output_shape_proto.into_iter() { + let value_kind = common::ValueKind::try_from(value_kind) + .map_err(|_| CommonRuntimeError::InvalidValue)?; + output_shape.insert(key, ValueKind::from(value_kind)); + } + + Ok(RuntimeIo::new(input, output_shape)) + } +} diff --git a/rust/common-runtime/src/runtime/mod.rs b/rust/common-runtime/src/runtime/mod.rs new file mode 100644 index 00000000..3e047e38 --- /dev/null +++ b/rust/common-runtime/src/runtime/mod.rs @@ -0,0 +1,8 @@ +#[cfg(not(target_arch = "wasm32"))] +pub mod wasmtime; + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +pub mod browser; + +mod io; +pub use io::*; diff --git a/rust/common-runtime/src/runtime/wasmtime/mod.rs b/rust/common-runtime/src/runtime/wasmtime/mod.rs new file mode 100644 index 00000000..359c20ed --- /dev/null +++ b/rust/common-runtime/src/runtime/wasmtime/mod.rs @@ -0,0 +1,3 @@ +mod runtime; + +pub use runtime::*; diff --git a/rust/common-runtime/src/runtime.rs b/rust/common-runtime/src/runtime/wasmtime/runtime.rs similarity index 69% rename from rust/common-runtime/src/runtime.rs rename to rust/common-runtime/src/runtime/wasmtime/runtime.rs index 0dd0ad51..1d70ef32 100644 --- a/rust/common-runtime/src/runtime.rs +++ b/rust/common-runtime/src/runtime/wasmtime/runtime.rs @@ -1,9 +1,10 @@ use crate::{ CommonRuntimeError, InputOutput, ModuleDefinition, ModuleInstance, ModuleInstanceId, - ModulePreparer, OutputShape, PreparedModule, ToModuleSources, ToWasmComponent, Value, + ModulePreparer, OutputShape, PreparedModule, Schedule, ToModuleSources, ToWasmComponent, Value, ValueKind, }; use common_protos::common; +use http::Uri; use std::collections::{BTreeMap, HashMap}; #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] @@ -15,53 +16,6 @@ use crate::wasmtime::{WasmtimeCompiler, WasmtimeInterpreter}; #[cfg(not(target_arch = "wasm32"))] use wasmtime::{Config, Engine, OptLevel}; -/// An implementation of [InputOutput] that is suitable for use with a -/// [Runtime]. -#[derive(Debug, Default, Clone)] -pub struct RuntimeIo { - input: BTreeMap, - output_shape: BTreeMap, - output: BTreeMap, -} - -impl RuntimeIo { - /// Instantiate a [RuntimeIo], providing initial input state, and the - /// expected shape of output state. - pub fn new(input: BTreeMap, output_shape: BTreeMap) -> Self { - Self { - input, - output_shape, - output: BTreeMap::new(), - } - } -} - -impl InputOutput for RuntimeIo { - fn read(&self, key: &str) -> Option { - self.input.get(key).cloned() - } - - fn write(&mut self, key: &str, value: Value) { - if let Some(kind) = self.output_shape.get(key) { - if value.is_of_kind(kind) { - self.output.insert(key.into(), value); - } else { - warn!("Ignoring write with unexpected shape to '{key}'"); - } - } else { - warn!("Ignoring write to unexpected output key '{key}'"); - } - } - - fn output(&self) -> &BTreeMap { - &self.output - } - - fn output_shape(&self) -> &OutputShape { - &self.output_shape - } -} - /// A [Runtime] is the main entrypoint for all Common Module instantiation and /// invocation. It manages the details of preparing Common Modules for /// instantiation, and appropriately sandboxing them ahead of invocation. @@ -83,6 +37,7 @@ pub struct Runtime { OutputShape, ), >, + // remote_runtime_address: Option, } impl Runtime { @@ -121,6 +76,7 @@ impl Runtime { &mut self, module: Module, io: RuntimeIo, + schedule: Schedule, ) -> Result { let output_shape = io.output_shape().clone(); debug!(?output_shape); @@ -144,6 +100,7 @@ impl Runtime { &mut self, module: Module, io: RuntimeIo, + schedule: Schedule, ) -> Result { let output_shape = io.output_shape().clone(); debug!(?output_shape); @@ -189,26 +146,3 @@ impl Runtime { instance.run(io).await } } - -impl TryFrom<(HashMap, HashMap)> for RuntimeIo { - type Error = CommonRuntimeError; - - fn try_from( - (input_proto, output_shape_proto): (HashMap, HashMap), - ) -> Result { - let mut input = BTreeMap::new(); - for (key, value) in input_proto.into_iter() { - input.insert(key, Value::try_from(value)?); - } - - let mut output_shape = BTreeMap::new(); - - for (key, value_kind) in output_shape_proto.into_iter() { - let value_kind = common::ValueKind::try_from(value_kind) - .map_err(|_| CommonRuntimeError::InvalidValue)?; - output_shape.insert(key, ValueKind::from(value_kind)); - } - - Ok(RuntimeIo::new(input, output_shape)) - } -} diff --git a/rust/common-runtime/src/runtime_experiment/mod.rs b/rust/common-runtime/src/runtime_experiment/mod.rs new file mode 100644 index 00000000..0ec1709b --- /dev/null +++ b/rust/common-runtime/src/runtime_experiment/mod.rs @@ -0,0 +1,234 @@ +// Targets + +use std::marker::PhantomData; + +struct CommonFunction; + +struct CommonFunctionVm; + +// Schedule + +struct PrefersLocal; + +struct PrefersRemote; + +// Module + +struct Module { + target: PhantomData, + schedule: PhantomData, + + runtime: R, +} + +// Instantiable + +trait Instantiable { + type ModuleInstance; + + fn instantiate(&mut self) -> Self::ModuleInstance; +} + +impl Instantiable for Module +where + R: LocalInstantiation + NativeMachine, +{ + type ModuleInstance = LocalFunction; + + fn instantiate(&mut self) -> Self::ModuleInstance { + LocalFunction {} + } +} + +impl Instantiable for Module +where + R: RemoteInstantiation + NativeMachine, +{ + type ModuleInstance = RemoteFunction; + + fn instantiate(&mut self) -> Self::ModuleInstance { + RemoteFunction {} + } +} + +impl Instantiable for Module +where + R: LocalInstantiation + VirtualMachine, +{ + type ModuleInstance = LocalFunctionScript; + + fn instantiate(&mut self) -> Self::ModuleInstance { + LocalFunctionScript {} + } +} + +impl Instantiable for Module +where + R: RemoteInstantiation + VirtualMachine, +{ + type ModuleInstance = RemoteFunctionScript; + + fn instantiate(&mut self) -> Self::ModuleInstance { + RemoteFunctionScript {} + } +} + +// Module + +pub trait FunctionInstance { + fn run(&self) {} +} + +pub struct LocalFunction {} +impl FunctionInstance for LocalFunction {} + +pub struct RemoteFunction {} +impl FunctionInstance for RemoteFunction {} + +pub struct LocalFunctionScript {} +impl FunctionInstance for LocalFunctionScript {} + +pub struct RemoteFunctionScript {} +impl FunctionInstance for RemoteFunctionScript {} + +// Runtime Capabilities + +pub trait LocalInstantiation {} + +pub trait RemoteInstantiation {} + +pub trait NativeMachine {} + +pub trait VirtualMachine {} + +// use std::collections::BTreeMap; +// use std::marker::PhantomData; + +// use common_wit::Target; + +// use crate::{ModuleSource, Schedule}; +// use crate::{SourceCode, ValueKind}; + +// struct CommonFunction; + +// impl From for Target { +// fn from(_: CommonFunction) -> Self { +// Target::CommonModule +// } +// } + +// struct CommonFunctionScript; + +// impl From for Target { +// fn from(value: CommonFunctionScript) -> Self { +// Target::CommonScript +// } +// } + +// struct LocalSchedule; + +// struct RemoteSchedule; + +// pub trait Runtime { +// fn inst(&mut self) -> I; +// } + +// pub trait LocalRuntime: Runtime {} + +// pub trait RemoteRuntime: Runtime {} + +// pub trait NativeEnvironmentRuntime: Runtime {} +// pub trait VirtualEnvironmentRuntime: Runtime {} + +// pub trait CommonFunctionInstance {} +// pub trait CommonFunctionScriptInstance {} + +// pub struct Module +// where +// T: Into, +// S: Into, +// R: Runtime, +// { +// target: T, +// schedule: S, +// runtime: R, + +// source: ModuleSource, +// inputs: BTreeMap, +// outputs: BTreeMap, +// } + +// impl Module +// where +// R: LocalRuntime, +// { +// pub async fn instantiate() -> M; +// } + +// #[derive(Default)] +// pub struct ModuleBuilder { +// target: Option, +// schedule: Option, +// runtime: Option, +// source_code: BTreeMap, +// inputs: BTreeMap, +// outputs: BTreeMap, +// } + +// impl ModuleBuilder { +// pub fn target(mut self, target: Target) -> Self { +// self.target = Some(target); +// self +// } + +// pub fn schedule(mut self, schedule: Schedule) -> Self { +// self.schedule = Some(schedule); +// self +// } + +// pub fn runtime(mut self, runtime: Runtime) -> Self { +// self.runtime = Some(runtime); +// self +// } + +// pub fn include_source_code(mut self, name: String, source_code: SourceCode) -> Self { +// self.source_code.insert(name, source_code); +// self +// } + +// pub fn expect_input(mut self, key: String, value_kind: ValueKind) -> Self { +// self.inputs.insert(key, value_kind); +// self +// } + +// pub fn provide_output(mut self, key: String, value_kind: ValueKind) -> Self { +// self.outputs.insert(key, value_kind); +// self +// } + +// pub fn build(self) -> Module {} +// } +// // impl ModuleBuilder { +// // pub fn runtime(&mut self, rt: R) +// // where +// // R: Ra, +// // { +// // } +// // } + +// // impl ModuleBuilder { +// // pub fn runtime(&mut self, rt: R) +// // where +// // R: Rb, +// // { +// // } +// // } + +// pub struct Module { +// target: T, +// schedule: S, +// runtime: R, +// source: ModuleSource, +// inputs: BTreeMap, +// outputs: BTreeMap, +// } diff --git a/rust/common-runtime/src/schedule.rs b/rust/common-runtime/src/schedule.rs new file mode 100644 index 00000000..7217f391 --- /dev/null +++ b/rust/common-runtime/src/schedule.rs @@ -0,0 +1,100 @@ +use std::cmp::Ordering; +use std::collections::{BTreeMap, BTreeSet}; + +use std::collections::HashSet; + +use common_wit::Target; +use http::Uri; + +use crate::{ModuleDefinition, ModuleId}; + +#[derive(Default, Debug, Clone)] +pub enum Frequency { + #[default] + Once, +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)] +pub enum Location { + #[default] + Local, + Remote(Uri), +} + +impl PartialOrd for Location { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Location { + fn cmp(&self, other: &Self) -> Ordering { + match self { + Location::Local => match other { + Location::Local => Ordering::Equal, + Location::Remote(_) => Ordering::Greater, + }, + Location::Remote(uri) => match other { + Location::Local => Ordering::Less, + Location::Remote(other_uri) => uri + .authority() + .partial_cmp(&other_uri.authority()) + .unwrap_or(Ordering::Equal), + }, + } + } +} + +#[derive(Default, Debug, Clone)] +pub struct Boundary(HashSet); + +impl Boundary { + pub fn add(&mut self, location: Location) -> &mut Self { + self.0.insert(location); + self + } + + pub fn intersect(&self, other: &Boundary) -> Boundary { + Boundary( + self.0 + .intersection(&other.0) + .map(|location| location.clone()) + .collect(), + ) + } + + pub fn get_schedulable(&self) -> Option { + self.0.iter().next().cloned() + } +} + +#[derive(Debug, Clone)] +pub struct Schedule { + pub frequency: Frequency, + pub boundary: Boundary, +} + +#[derive(Default, Debug)] +pub struct ScheduleBuilder { + frequency: Frequency, + boundary: Boundary, +} + +impl ScheduleBuilder { + pub fn frequency(&mut self, frequency: Frequency) -> &mut Self { + self.frequency = frequency; + self + } + + pub fn allow_location(&mut self, location: Location) -> &mut Self { + self.boundary.add(location); + self + } + + pub fn build(self) -> Schedule { + Schedule { + frequency: self.frequency, + boundary: self.boundary, + } + } +} diff --git a/rust/common-wit/build.rs b/rust/common-wit/build.rs index cf88a044..c28344ad 100644 --- a/rust/common-wit/build.rs +++ b/rust/common-wit/build.rs @@ -5,7 +5,7 @@ const TYPESCRIPT_SOURCE_DEPENDENCIES: &[&str] = &[ "package-lock.json", "common/io/wit/io.wit", "common/data/wit/data.wit", - "common/module/wit/module.wit", + "common/function/wit/function.wit", ]; fn main() { diff --git a/rust/common-wit/src/lib.rs b/rust/common-wit/src/lib.rs index 40419f1b..455d44c1 100644 --- a/rust/common-wit/src/lib.rs +++ b/rust/common-wit/src/lib.rs @@ -8,8 +8,8 @@ use std::{collections::BTreeMap, str::FromStr}; use serde::{Deserialize, Serialize}; /// WIT definition for `common:module` -pub const COMMON_MODULE_WIT: &[u8] = - include_bytes!("../../../typescript/common/module/wit/module.wit"); +pub const COMMON_FUNCTION_WIT: &[u8] = + include_bytes!("../../../typescript/common/function/wit/function.wit"); /// WIT definition for `common:io` pub const COMMON_IO_WIT: &[u8] = include_bytes!("../../../typescript/common/io/wit/io.wit"); @@ -17,26 +17,23 @@ pub const COMMON_IO_WIT: &[u8] = include_bytes!("../../../typescript/common/io/w /// WIT definition for `common:data` pub const COMMON_DATA_WIT: &[u8] = include_bytes!("../../../typescript/common/data/wit/data.wit"); -/// WIT definition for `common:script` -pub const COMMON_SCRIPT_WIT: &[u8] = - include_bytes!("../../../typescript/common/script/wit/script.wit"); - /// A target that some candidate source code may express the implementation of #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum Target { /// The most basic target: a Common Module - #[serde(rename = "common:module")] - CommonModule, + #[serde(rename = "common:function/module")] + CommonFunction, /// Effectively the same as a Common Module, but intepreted w/o a compile step - #[serde(rename = "common:script")] - CommonScript, + #[serde(rename = "common:function/virtual-module")] + CommonFunctionVm, } impl Target { /// The presumptive WIT world that corresponds to a give [WitTarget] pub fn world(&self) -> &'static str { match self { - Target::CommonModule | Target::CommonScript => "common", + Target::CommonFunction => "module", + Target::CommonFunctionVm => "virtual-module", } } } @@ -46,8 +43,8 @@ impl FromStr for Target { fn from_str(s: &str) -> Result { Ok(match s { - "common:module" => Target::CommonModule, - "common:script" => Target::CommonScript, + "common:function/module" => Target::CommonFunction, + "common:function/virtual-module" => Target::CommonFunctionVm, _ => { return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, @@ -64,8 +61,8 @@ impl std::fmt::Display for Target { f, "{}", match self { - Target::CommonModule => "common:module", - Target::CommonScript => "common:script", + Target::CommonFunction => "common:function/module", + Target::CommonFunctionVm => "common:function/virtual-module", } ) } @@ -138,14 +135,8 @@ impl From for WitTargetFileMap { impl From<&Target> for WitTargetFileMap { fn from(value: &Target) -> Self { WitTargetFileMap(match value { - Target::CommonScript => BTreeMap::from([ - ("target.wit".into(), COMMON_SCRIPT_WIT), - ("deps/io/io.wit".into(), COMMON_IO_WIT), - ("deps/data/data.wit".into(), COMMON_DATA_WIT), - ("deps/module/module.wit".into(), COMMON_MODULE_WIT), - ]), - Target::CommonModule => BTreeMap::from([ - ("target.wit".into(), COMMON_MODULE_WIT), + Target::CommonFunction | Target::CommonFunctionVm => BTreeMap::from([ + ("target.wit".into(), COMMON_FUNCTION_WIT), ("deps/io/io.wit".into(), COMMON_IO_WIT), ("deps/data/data.wit".into(), COMMON_DATA_WIT), ]), @@ -163,7 +154,7 @@ mod tests { #[tokio::test] async fn it_can_write_a_wit_hierarchy_to_the_file_system() -> Result<()> { let output = TempDir::new()?; - let file_map: WitTargetFileMap = Target::CommonModule.into(); + let file_map: WitTargetFileMap = Target::CommonFunction.into(); file_map.clone().write_to(output.path()).await?; diff --git a/typescript/common/data/package.json b/typescript/common/data/package.json index bd043e5c..8cba08de 100644 --- a/typescript/common/data/package.json +++ b/typescript/common/data/package.json @@ -28,12 +28,12 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/commontoolsinc/labs.git" + "url": "git+https://github.com/commontoolsinc/system.git" }, "bugs": { - "url": "https://github.com/commontoolsinc/labs/issues" + "url": "https://github.com/commontoolsinc/system/issues" }, - "homepage": "https://github.com/commontoolsinc/labs#readme", + "homepage": "https://github.com/commontoolsinc/system#readme", "dependencies": {}, "devDependencies": { "@bytecodealliance/jco": "^1.3.1", @@ -91,9 +91,9 @@ "dependencies": [ "build:jco" ], - "command": "cat ./wit/*.wit | ../module/scripts/generate-wit-module.sh > ./lib/index.js", + "command": "cat ./wit/*.wit | ../function/scripts/generate-wit-module.sh > ./lib/index.js", "files": [ - "../module/scripts/generate-wit-module.sh", + "../function/scripts/generate-wit-module.sh", "./wit/*.wit" ] }, diff --git a/typescript/common/module/package.json b/typescript/common/function/package.json similarity index 82% rename from typescript/common/module/package.json rename to typescript/common/function/package.json index 9760e6be..2c3c4c0e 100644 --- a/typescript/common/module/package.json +++ b/typescript/common/function/package.json @@ -1,5 +1,5 @@ { - "name": "@commontools/module", + "name": "@commontools/function", "author": "The Common Authors", "version": "0.0.1", "description": "", @@ -21,12 +21,12 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/commontoolsinc/labs.git" + "url": "git+https://github.com/commontoolsinc/system.git" }, "bugs": { - "url": "https://github.com/commontoolsinc/labs/issues" + "url": "https://github.com/commontoolsinc/system/issues" }, - "homepage": "https://github.com/commontoolsinc/labs#readme", + "homepage": "https://github.com/commontoolsinc/system#readme", "dependencies": {}, "devDependencies": { "@bytecodealliance/jco": "^1.3.1", @@ -72,7 +72,7 @@ "install:wit", "lint:wit" ], - "command": "jco types -o ./lib --name index ./wit", + "command": "jco types -o ./lib --world-name module --name index ./wit", "files": [ "./wit/**/*" ], @@ -84,9 +84,9 @@ "dependencies": [ "build:jco" ], - "command": "cat ./wit/*.wit | ../module/scripts/generate-wit-module.sh > ./lib/index.js", + "command": "cat ./wit/*.wit | ../function/scripts/generate-wit-module.sh > ./lib/index.js", "files": [ - "../module/scripts/generate-wit-module.sh", + "../function/scripts/generate-wit-module.sh", "./wit/*.wit" ] }, diff --git a/typescript/common/module/scripts/generate-wit-module.sh b/typescript/common/function/scripts/generate-wit-module.sh similarity index 100% rename from typescript/common/module/scripts/generate-wit-module.sh rename to typescript/common/function/scripts/generate-wit-module.sh diff --git a/typescript/common/module/wit/deps.lock b/typescript/common/function/wit/deps.lock similarity index 100% rename from typescript/common/module/wit/deps.lock rename to typescript/common/function/wit/deps.lock diff --git a/typescript/common/module/wit/deps.toml b/typescript/common/function/wit/deps.toml similarity index 100% rename from typescript/common/module/wit/deps.toml rename to typescript/common/function/wit/deps.toml diff --git a/typescript/common/module/wit/module.wit b/typescript/common/function/wit/function.wit similarity index 59% rename from typescript/common/module/wit/module.wit rename to typescript/common/function/wit/function.wit index 22a30d6b..a16d4d8a 100644 --- a/typescript/common/module/wit/module.wit +++ b/typescript/common/function/wit/function.wit @@ -1,14 +1,20 @@ -package common:module@0.0.1; +package common:function@0.0.1; interface reflect { input-keys: func() -> list; output-keys: func() -> list; } -world common { +world module { import common:data/types@0.0.1; import common:io/state@0.0.1; import reflect; export run: func() -> result<_, string>; +} + +world virtual-module { + include module; + + export set-source: func(source: string) -> result<_, string>; } \ No newline at end of file diff --git a/typescript/common/io/package.json b/typescript/common/io/package.json index 8f0291c1..2fd76171 100644 --- a/typescript/common/io/package.json +++ b/typescript/common/io/package.json @@ -21,12 +21,12 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/commontoolsinc/labs.git" + "url": "git+https://github.com/commontoolsinc/system.git" }, "bugs": { - "url": "https://github.com/commontoolsinc/labs/issues" + "url": "https://github.com/commontoolsinc/system/issues" }, - "homepage": "https://github.com/commontoolsinc/labs#readme", + "homepage": "https://github.com/commontoolsinc/system#readme", "dependencies": {}, "devDependencies": { "@bytecodealliance/jco": "^1.3.1", @@ -84,9 +84,9 @@ "dependencies": [ "build:jco" ], - "command": "cat ./wit/*.wit | ../module/scripts/generate-wit-module.sh > ./lib/index.js", + "command": "cat ./wit/*.wit | ../function/scripts/generate-wit-module.sh > ./lib/index.js", "files": [ - "../module/scripts/generate-wit-module.sh", + "../function/scripts/generate-wit-module.sh", "./wit/*.wit" ] }, diff --git a/typescript/common/script/package.json b/typescript/common/script/package.json deleted file mode 100644 index 124c15c6..00000000 --- a/typescript/common/script/package.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "name": "@commontools/script", - "author": "The Common Authors", - "version": "0.0.1", - "description": "", - "license": "UNLICENSED", - "private": true, - "type": "module", - "types": "./lib/module.d.ts", - "files": [ - "./lib/**/*" - ], - "exports": "./lib/index.js", - "scripts": { - "build": "wireit", - "clean": "wireit", - "prepare": "wireit", - "update:wit": "wireit", - "lint:wit": "wireit", - "build:wit:inline": "wireit" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/commontoolsinc/labs.git" - }, - "bugs": { - "url": "https://github.com/commontoolsinc/labs/issues" - }, - "homepage": "https://github.com/commontoolsinc/labs#readme", - "dependencies": {}, - "devDependencies": { - "@bytecodealliance/jco": "^1.3.1", - "typescript": "^5.5.4", - "wireit": "^0.14.4" - }, - "wireit": { - "prepare": { - "dependencies": [ - "install:wit" - ] - }, - "install:wit": { - "command": "wit-deps", - "files": [ - "./wit/deps.*" - ], - "output": [ - "./wit/deps/**/*" - ] - }, - "lint:wit": { - "dependencies": [ - "install:wit" - ], - "command": "wasm-tools component wit ./wit", - "files": [ - "./wit/**/*" - ] - }, - "update:wit": { - "command": "wit-deps update", - "files": [ - "./wit/deps.toml" - ], - "output": [ - "./wit/deps.lock", - "./wit/deps/**/*" - ] - }, - "build:jco": { - "dependencies": [ - "install:wit", - "lint:wit" - ], - "command": "jco types -o ./lib --name index ./wit", - "files": [ - "./wit/**/*" - ], - "output": [ - "./lib/**/*" - ] - }, - "build:wit:index": { - "dependencies": [ - "build:jco" - ], - "command": "cat ./wit/*.wit | ../module/scripts/generate-wit-module.sh > ./lib/index.js", - "files": [ - "../module/scripts/generate-wit-module.sh", - "./wit/*.wit" - ] - }, - "build:wit:types": { - "dependencies": [ - "build:jco" - ], - "command": "echo 'export const wit: string;' >> ./lib/index.d.ts", - "files": [ - "./lib/index.d.ts" - ] - }, - "build:wit": { - "dependencies": [ - "build:wit:index", - "build:wit:types" - ] - }, - "build": { - "dependencies": [ - "build:jco", - "build:wit" - ] - }, - "clean": { - "command": "rm -rf ./src ./lib ./.wireit ./wit/deps" - } - } -} \ No newline at end of file diff --git a/typescript/common/script/wit/deps.lock b/typescript/common/script/wit/deps.lock deleted file mode 100644 index 4c6e2ad0..00000000 --- a/typescript/common/script/wit/deps.lock +++ /dev/null @@ -1,14 +0,0 @@ -[data] -path = "../../data/wit" -sha256 = "edb3fa962337292260fb5e1257b6a7f770d6f4a2865c88ddb68a7f4fb8169bbd" -sha512 = "aa6f16d180975d35dde3ebcd1b6a21992ee9e38ba9edf3f5535ff3415c3933792c8be5a9a9233e02ac713c3ac129a6f2f65b734f357c6405ddbbff69ebe3f793" - -[io] -path = "../../io/wit" -sha256 = "3d6c8ae11439a90d1260d64030dc9ac003a72f2f7277df787b95c5a8f54d7474" -sha512 = "87c77c5a22fdc2c9850ff9e6672f94a86c7c32a6f665d714caca5613f6bc2a1cca76d7ebb26ddf3bae80c32d5d692baab803aff61207aaaa87ffdbd8e6cdc109" - -[module] -path = "../../module/wit" -sha256 = "cc4b0b5358ef2f51743b26a09a4a81bca23cb647f0561691387d28bc48dbbd26" -sha512 = "7ff0a2fc4fa76decae57a3a8b8ee7f68c25c813eb1405e90e0c89a8045056b9cf5c1f3fa419845579cf920fd7e00f9c923b25664dc282dbff232a1dbd6e295d2" diff --git a/typescript/common/script/wit/deps.toml b/typescript/common/script/wit/deps.toml deleted file mode 100644 index fd975e43..00000000 --- a/typescript/common/script/wit/deps.toml +++ /dev/null @@ -1,3 +0,0 @@ -data = "../../data/wit" -io = "../../io/wit" -module = "../../module/wit" \ No newline at end of file diff --git a/typescript/common/script/wit/script.wit b/typescript/common/script/wit/script.wit deleted file mode 100644 index ab3fb7ed..00000000 --- a/typescript/common/script/wit/script.wit +++ /dev/null @@ -1,7 +0,0 @@ -package common:script@0.0.1; - -world common { - include common:module/common@0.0.1; - - export set-source: func(source: string) -> result<_, string>; -} \ No newline at end of file diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 11568ab4..2fb76e4f 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -25,6 +25,15 @@ "wireit": "^0.14.5" } }, + "common/function": { + "version": "0.0.1", + "license": "UNLICENSED", + "devDependencies": { + "@bytecodealliance/jco": "^1.3.1", + "typescript": "^5.5.4", + "wireit": "^0.14.5" + } + }, "common/io": { "name": "@commontools/io", "version": "0.0.1", @@ -38,6 +47,7 @@ "common/module": { "name": "@commontools/module", "version": "0.0.1", + "extraneous": true, "license": "UNLICENSED", "devDependencies": { "@bytecodealliance/jco": "^1.3.1", @@ -48,6 +58,7 @@ "common/script": { "name": "@commontools/script", "version": "0.0.1", + "extraneous": true, "license": "UNLICENSED", "devDependencies": { "@bytecodealliance/jco": "^1.3.1", @@ -83,16 +94,12 @@ "resolved": "common/data", "link": true }, - "node_modules/@commontools/io": { - "resolved": "common/io", + "node_modules/@commontools/function": { + "resolved": "common/function", "link": true }, - "node_modules/@commontools/module": { - "resolved": "common/module", - "link": true - }, - "node_modules/@commontools/script": { - "resolved": "common/script", + "node_modules/@commontools/io": { + "resolved": "common/io", "link": true }, "node_modules/@jridgewell/gen-mapping": { diff --git a/typescript/package.json b/typescript/package.json index 9c8a7322..ea5b0495 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -15,12 +15,12 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/commontoolsinc/labs.git" + "url": "git+https://github.com/commontoolsinc/system.git" }, "bugs": { - "url": "https://github.com/commontoolsinc/labs/issues" + "url": "https://github.com/commontoolsinc/system/issues" }, - "homepage": "https://github.com/commontoolsinc/labs#readme", + "homepage": "https://github.com/commontoolsinc/system#readme", "devDependencies": { "wireit": "^0.14.5" }, @@ -29,16 +29,14 @@ "dependencies": [ "./common/data:build", "./common/io:build", - "./common/module:build", - "./common/script:build" + "./common/function:build" ] }, "clean": { "dependencies": [ "./common/data:clean", "./common/io:clean", - "./common/module:clean", - "./common/script:clean" + "./common/function:clean" ] } },