diff --git a/.gitignore b/.gitignore
index b9c8bc6e2..5e46eb408 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
target
.wireit
node_modules
-dist
\ No newline at end of file
+dist
+lib
+*.tsbuildinfo
diff --git a/Cargo.lock b/Cargo.lock
index 26808daa5..e5688df2d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -327,13 +327,6 @@ dependencies = [
"windows-sys 0.52.0",
]
-[[package]]
-name = "example-crate"
-version = "0.1.0"
-dependencies = [
- "wit-bindgen",
-]
-
[[package]]
name = "fallible-iterator"
version = "0.3.0"
@@ -1396,6 +1389,22 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "tower-http"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
+dependencies = [
+ "bitflags",
+ "bytes",
+ "http",
+ "http-body",
+ "http-body-util",
+ "pin-project-lite",
+ "tower-layer",
+ "tower-service",
+]
+
[[package]]
name = "tower-layer"
version = "0.3.2"
@@ -1558,10 +1567,12 @@ dependencies = [
name = "usuba"
version = "0.1.0"
dependencies = [
+ "anyhow",
"async-trait",
"axum",
"blake3",
"bytes",
+ "hyper-util",
"mime_guess",
"redb",
"rust-embed",
@@ -1570,16 +1581,19 @@ dependencies = [
"tempfile",
"thiserror",
"tokio",
+ "tower-http",
"tracing",
"tracing-subscriber",
"utoipa",
"utoipa-swagger-ui",
+ "wit-parser 0.208.1",
]
[[package]]
name = "usuba-compat"
version = "0.1.0"
dependencies = [
+ "blake3",
"js-component-bindgen",
"wasmtime-environ",
"wit-bindgen",
diff --git a/Cargo.toml b/Cargo.toml
index d1bc1843c..faa2002a0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,5 @@
[workspace]
members = [
- "rust/example-crate",
"rust/usuba",
"rust/usuba-compat"
]
@@ -9,10 +8,12 @@ members = [
resolver = "2"
[workspace.dependencies]
+anyhow = { version = "1" }
async-trait = { version = "0.1" }
axum = { version = "0.7" }
blake3 = { version = "1.5" }
bytes = { version = "1" }
+hyper-util = { version = "0.1", features = ["client", "client-legacy"] }
js-component-bindgen = { version = "1", features = ["transpile-bindgen"] }
js-sys = { version = "0.3" }
mime_guess = { version = "2" }
@@ -23,6 +24,7 @@ serde_json = { version = "1" }
tempfile = { version = "3" }
thiserror = { version = "1" }
tokio = { version = "1" }
+tower-http = { version = "0.5" }
tracing = { version = "0.1" }
tracing-subscriber = { version = "0.3", features = ["env-filter", "tracing-log", "json"] }
tracing-web = { version = "0.1" }
@@ -32,7 +34,8 @@ wasm-bindgen = { version = "0.2" }
wasmtime-environ = { version = "20" }
web-sys = { version = "0.3" }
wit-bindgen = { version = "0.25" }
+wit-parser = { version = "0.208" }
[profile.release]
opt-level = 'z'
-lto = true
\ No newline at end of file
+lto = true
diff --git a/rust/example-crate/Cargo.toml b/rust/example-crate/Cargo.toml
deleted file mode 100644
index 25ee8d9d8..000000000
--- a/rust/example-crate/Cargo.toml
+++ /dev/null
@@ -1,23 +0,0 @@
-[package]
-name = "example-crate"
-version = "0.1.0"
-edition = "2021"
-description = "A Rust library that works on the web, in Deno and natively"
-keywords = ["example"]
-categories = [
- "command-line interface"
-]
-rust-version = "1.75.0"
-license = "UNLICENSED"
-documentation = "https://github.com/commontoolsinc/labs"
-repository = "https://github.com/commontoolsinc/labs"
-homepage = "https://github.com/commontoolsinc/labs"
-readme = "README.md"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-[lib]
-crate-type = ["cdylib", "rlib"]
-
-[dependencies]
-wit-bindgen = { workspace = true }
-
diff --git a/rust/example-crate/README.md b/rust/example-crate/README.md
deleted file mode 100644
index 2570cd8f5..000000000
--- a/rust/example-crate/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Example Crate
-
-This crate implements a simple Rust library. It is able to be used in typical Rust programs, and it is also able to be compiled as a Wasm Component and run anywhere such a thing may be run (e.g., web browsers, Deno etc).
-
-## Usage
-
-To run a demo on your local target: `cargo run`.
-
-To build a Wasm Component for the web: `./build-wasm-component.sh`
-
-## References
-
-- Wasm components: https://github.com/WebAssembly/component-model
-- WIT: https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md
-- WASI interfaces: https://wasi.dev/interfaces
-- `wasm-tools`: https://github.com/bytecodealliance/wasm-tools
-- `cargo-component`: https://github.com/bytecodealliance/cargo-component
-- `warg`: https://warg.io/
- - "A secure registry protocol for Wasm packages"
-- "Making JavaScript run fast on WebAssembly": https://bytecodealliance.org/articles/making-javascript-run-fast-on-webassembly
-- "Changes to Rust's WASI targets": https://blog.rust-lang.org/2024/04/09/updates-to-rusts-wasi-targets.html
\ No newline at end of file
diff --git a/rust/example-crate/build-wasm-component.sh b/rust/example-crate/build-wasm-component.sh
deleted file mode 100755
index a4c17503a..000000000
--- a/rust/example-crate/build-wasm-component.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env bash
-
-set -euxo pipefail
-
-SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
-pushd $SCRIPT_DIR
-
-cargo build --release --target wasm32-wasi
-
-pushd ../../target/wasm32-wasi/release
-
-if [[ ! -f ./wasi_snapshot_preview1_reactor.wasm ]]; then
- wget https://github.com/bytecodealliance/wasmtime/releases/download/v20.0.2/wasi_snapshot_preview1.reactor.wasm
-fi
-
-wasm-tools component new \
- ./example_crate.wasm \
- -o example_component.wasm \
- --adapt ./wasi_snapshot_preview1.reactor.wasm
-
-jco transpile ./example_component.wasm \
- -o ./example_component_package
-
-popd
-popd
\ No newline at end of file
diff --git a/rust/example-crate/src/bin/cowsay.rs b/rust/example-crate/src/bin/cowsay.rs
deleted file mode 100644
index 085c73523..000000000
--- a/rust/example-crate/src/bin/cowsay.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-use example_crate::{Cows, Cowsayer};
-
-pub fn main() {
- println!("{}", Cowsayer::say("moo".into(), None));
- println!("{}", Cowsayer::say("hoo".into(), Some(Cows::Owl)));
-}
diff --git a/rust/example-crate/src/cowsayer/component.rs b/rust/example-crate/src/cowsayer/component.rs
deleted file mode 100644
index 111c8738a..000000000
--- a/rust/example-crate/src/cowsayer/component.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Generates a "guest" trait based on the specified [WIT][1] definition
-//
-// [1]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md
-wit_bindgen::generate!({
- world: "cowsay",
-});
-
-use super::native::{Cows as NativeCows, Cowsayer as NativeCowsayer};
-use exports::cow::{Cows, Guest};
-
-impl From for NativeCows {
- fn from(value: Cows) -> Self {
- match value {
- Cows::Default => NativeCows::Cow,
- Cows::Owl => NativeCows::Owl,
- }
- }
-}
-
-struct Cowsayer;
-
-impl Guest for Cowsayer {
- fn say(text: String, cow: Option) -> String {
- NativeCowsayer::say(text, cow.map(|cow| cow.into()))
- }
-}
-
-// Macro generates exportable Wasm Component functions that call into our
-// implementation
-export!(Cowsayer);
diff --git a/rust/example-crate/src/cowsayer/mod.rs b/rust/example-crate/src/cowsayer/mod.rs
deleted file mode 100644
index 9fc3ac236..000000000
--- a/rust/example-crate/src/cowsayer/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-mod native;
-
-pub use native::*;
-
-#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
-mod component;
-
-#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
-pub use component::*;
diff --git a/rust/example-crate/src/cowsayer/native.rs b/rust/example-crate/src/cowsayer/native.rs
deleted file mode 100644
index 8960e3b69..000000000
--- a/rust/example-crate/src/cowsayer/native.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-pub enum Cows {
- Cow,
- Owl,
-}
-
-// A token struct that will implement the "guest" trait
-pub struct Cowsayer;
-
-impl Cowsayer {
- pub fn say(text: String, cow: Option) -> String {
- match cow {
- Some(Cows::Owl) => {
- format!(
- r#"{text}
- ___
- (o o)
- ( V )
-/--m-m-"#
- )
- }
- _ => {
- format!(
- r#"{text}
- \\ ^__^
- \\ (oo)\\______
- (__)\\ )\/\\
- ||----w |
- || ||"#
- )
- }
- }
- }
-}
diff --git a/rust/example-crate/src/lib.rs b/rust/example-crate/src/lib.rs
deleted file mode 100644
index 9e29fbbbf..000000000
--- a/rust/example-crate/src/lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-mod cowsayer;
-
-pub use cowsayer::*;
diff --git a/rust/example-crate/wit/cowsay.wit b/rust/example-crate/wit/cowsay.wit
deleted file mode 100644
index 45c41c2e7..000000000
--- a/rust/example-crate/wit/cowsay.wit
+++ /dev/null
@@ -1,12 +0,0 @@
-package local:cowsay;
-
-world cowsay {
- export cow: interface {
- enum cows {
- default,
- owl
- }
-
- say: func(text: string, cow: option) -> string;
- }
-}
\ No newline at end of file
diff --git a/rust/usuba-compat/Cargo.toml b/rust/usuba-compat/Cargo.toml
index 2eb428e60..dcceeead1 100644
--- a/rust/usuba-compat/Cargo.toml
+++ b/rust/usuba-compat/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
crate-type = ["cdylib", "rlib"]
[dependencies]
+blake3 = { workspace = true }
js-component-bindgen = { workspace = true }
wit-bindgen = { workspace = true }
wasmtime-environ = { workspace = true, features = ["component-model", "compile"] }
\ No newline at end of file
diff --git a/rust/usuba-compat/build-wasm-component.sh b/rust/usuba-compat/build-wasm-component.sh
index 3a8f8ede2..01dc2a771 100755
--- a/rust/usuba-compat/build-wasm-component.sh
+++ b/rust/usuba-compat/build-wasm-component.sh
@@ -18,7 +18,7 @@ wasm-tools component new \
-o usuba_compat.component.wasm \
--adapt ./wasi_snapshot_preview1.reactor.wasm
-jco transpile -O --tla-compat ./usuba_compat.component.wasm \
+jco transpile --tla-compat ./usuba_compat.component.wasm \
-o ./usuba_compat
popd
diff --git a/rust/usuba-compat/src/lib.rs b/rust/usuba-compat/src/lib.rs
index 9620f27ab..3b7d5adb1 100644
--- a/rust/usuba-compat/src/lib.rs
+++ b/rust/usuba-compat/src/lib.rs
@@ -1,4 +1,4 @@
-use js_component_bindgen::{transpile, TranspileOpts, Transpiled};
+use js_component_bindgen::{transpile, InstantiationMode, TranspileOpts, Transpiled};
use wasmtime_environ::component::Export as WasmtimeExport;
wit_bindgen::generate!({
@@ -15,7 +15,10 @@ impl Guest for Polyfill {
.mappings
.map(|mappings| mappings.into_iter().collect()),
no_typescript: true,
- instantiation: None,
+ instantiation: options
+ .instantiation
+ .unwrap_or_else(|| Instantiation::Automatic)
+ .into(),
import_bindings: None,
no_nodejs_compat: true,
base64_cutoff: 1024,
@@ -30,10 +33,23 @@ impl Guest for Polyfill {
.map(|transpiled| transpiled.into())
.map_err(|error| format!("{}", error))
}
+
+ fn hash(bytes: Vec) -> String {
+ blake3::hash(&bytes).to_string()
+ }
}
export!(Polyfill);
+impl From for Option {
+ fn from(value: Instantiation) -> Self {
+ match value {
+ Instantiation::Automatic => None,
+ Instantiation::Manual => Some(InstantiationMode::Async),
+ }
+ }
+}
+
impl From for Artifacts {
fn from(value: Transpiled) -> Self {
Artifacts {
diff --git a/rust/usuba-compat/wit/usuba-compat.wit b/rust/usuba-compat/wit/usuba-compat.wit
index 04e25250f..fd4bd5510 100644
--- a/rust/usuba-compat/wit/usuba-compat.wit
+++ b/rust/usuba-compat/wit/usuba-compat.wit
@@ -6,7 +6,13 @@ world usuba-compat {
record polyfill-options {
name: string,
- mappings: option
+ mappings: option,
+ instantiation: option
+ }
+
+ enum instantiation {
+ automatic,
+ manual
}
enum export-type {
@@ -21,4 +27,5 @@ world usuba-compat {
}
export polyfill: func(component: list, options: polyfill-options) -> result;
+ export hash: func(bytes: list) -> string;
}
\ No newline at end of file
diff --git a/rust/usuba/Cargo.toml b/rust/usuba/Cargo.toml
index effb467cb..d49d5c8c9 100644
--- a/rust/usuba/Cargo.toml
+++ b/rust/usuba/Cargo.toml
@@ -7,10 +7,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+anyhow = { workspace = true }
async-trait = { workspace = true }
axum = { workspace = true, features = ["multipart"] }
blake3 = { workspace = true }
bytes = { workspace = true }
+hyper-util = { workspace = true }
mime_guess = { workspace = true }
redb = { workspace = true }
rust-embed = { workspace = true }
@@ -19,9 +21,11 @@ serde_json = { workspace = true }
tempfile = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "io-util", "process", "fs"] }
+tower-http = { workspace = true, features = ["cors"] }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
utoipa = { workspace = true, features = ["axum_extras"] }
utoipa-swagger-ui = { workspace = true, features = ["axum"] }
+wit-parser = { workspace = true }
# gcloud-sdk = { version = "0.24.6", features = ["google-cloud-aiplatform-v1"] }
diff --git a/rust/usuba/src/bake/bake.rs b/rust/usuba/src/bake/bake.rs
index 638521c6e..27dba5694 100644
--- a/rust/usuba/src/bake/bake.rs
+++ b/rust/usuba/src/bake/bake.rs
@@ -4,5 +4,11 @@ use bytes::Bytes;
#[async_trait]
pub trait Bake {
- async fn bake(&self, wit: Bytes, source_code: Bytes) -> Result;
+ async fn bake(
+ &self,
+ world: &str,
+ wit: Vec,
+ source_code: Bytes,
+ library: Vec,
+ ) -> Result;
}
diff --git a/rust/usuba/src/bake/fs.rs b/rust/usuba/src/bake/fs.rs
new file mode 100644
index 000000000..a2b586e0b
--- /dev/null
+++ b/rust/usuba/src/bake/fs.rs
@@ -0,0 +1,12 @@
+use std::{io::Cursor, path::PathBuf};
+
+use bytes::Bytes;
+
+use crate::UsubaError;
+
+pub async fn write_file(path: PathBuf, bytes: Bytes) -> Result<(), UsubaError> {
+ let mut file = tokio::fs::File::create(&path).await?;
+ let mut cursor = Cursor::new(bytes.as_ref());
+ tokio::io::copy(&mut cursor, &mut file).await?;
+ Ok(())
+}
diff --git a/rust/usuba/src/bake/javascript.rs b/rust/usuba/src/bake/javascript.rs
index ed7a4baee..70decac21 100644
--- a/rust/usuba/src/bake/javascript.rs
+++ b/rust/usuba/src/bake/javascript.rs
@@ -1,4 +1,3 @@
-use std::io::Cursor;
use tracing::instrument;
use super::Bake;
@@ -7,6 +6,9 @@ use bytes::Bytes;
use tempfile::TempDir;
use tokio::process::Command;
+use tokio::task::JoinSet;
+
+use crate::write_file;
#[derive(Debug)]
pub struct JavaScriptBaker {}
@@ -14,7 +16,13 @@ pub struct JavaScriptBaker {}
#[async_trait]
impl Bake for JavaScriptBaker {
#[instrument]
- async fn bake(&self, wit: Bytes, source_code: Bytes) -> Result {
+ async fn bake(
+ &self,
+ world: &str,
+ wit: Vec,
+ source_code: Bytes,
+ library: Vec,
+ ) -> Result {
let workspace = TempDir::new()?;
debug!(
"Created temporary workspace in {}",
@@ -23,31 +31,42 @@ impl Bake for JavaScriptBaker {
let wasm_path = workspace.path().join("module.wasm");
let js_path = workspace.path().join("module.js");
- let wit_path = workspace.path().join("module.wit");
- let (mut wit_file, mut js_file) = tokio::try_join!(
- tokio::fs::File::create(&wit_path),
- tokio::fs::File::create(&js_path),
- )?;
+ debug!(?workspace, "Created temporary workspace");
+
+ let wit_path = workspace.path().join("wit");
+ let wit_deps_path = wit_path.join("deps");
- debug!(?wit_path, ?js_path, "Created temporary input files");
+ tokio::fs::create_dir_all(&wit_deps_path).await?;
- let mut wit_cursor = Cursor::new(wit);
- let mut js_cursor = Cursor::new(source_code);
+ let mut writes = JoinSet::new();
- tokio::try_join!(
- tokio::io::copy(&mut wit_cursor, &mut wit_file),
- tokio::io::copy(&mut js_cursor, &mut js_file),
- )?;
+ wit.into_iter()
+ .enumerate()
+ .map(|(i, wit)| write_file(wit_path.join(format!("module{}.wit", i)), wit))
+ .chain([write_file(js_path.clone(), source_code)])
+ .chain(
+ library.into_iter().enumerate().map(|(i, wit)| {
+ write_file(wit_deps_path.join(format!("library{}.wit", i)), wit)
+ }),
+ )
+ .for_each(|fut| {
+ writes.spawn(fut);
+ });
+
+ while let Some(result) = writes.try_join_next() {
+ result??;
+ continue;
+ }
- debug!(?wit_path, ?js_path, "Populated temporary input files");
+ debug!(?workspace, "Populated temporary input files");
let mut command = Command::new("jco");
command
.arg("componentize")
.arg("-w")
- .arg(wit_path.display().to_string())
+ .arg(wit_path)
.arg("-o")
.arg(wasm_path.display().to_string())
.arg(js_path.display().to_string());
diff --git a/rust/usuba/src/bake/mod.rs b/rust/usuba/src/bake/mod.rs
index fde35aff0..3e4935879 100644
--- a/rust/usuba/src/bake/mod.rs
+++ b/rust/usuba/src/bake/mod.rs
@@ -1,21 +1,41 @@
mod bake;
+mod fs;
mod javascript;
+mod python;
pub use bake::*;
+pub use fs::*;
pub use javascript::*;
+pub use python::*;
use async_trait::async_trait;
use bytes::Bytes;
pub enum Baker {
JavaScript,
+ Python,
}
#[async_trait]
impl Bake for Baker {
- async fn bake(&self, wit: Bytes, source_code: Bytes) -> Result {
+ async fn bake(
+ &self,
+ world: &str,
+ wit: Vec,
+ source_code: Bytes,
+ library: Vec,
+ ) -> Result {
match self {
- Baker::JavaScript => (JavaScriptBaker {}).bake(wit, source_code).await,
+ Baker::JavaScript => {
+ (JavaScriptBaker {})
+ .bake(world, wit, source_code, library)
+ .await
+ }
+ Baker::Python => {
+ (PythonBaker {})
+ .bake(world, wit, source_code, library)
+ .await
+ }
}
}
}
diff --git a/rust/usuba/src/bake/python.rs b/rust/usuba/src/bake/python.rs
new file mode 100644
index 000000000..262bb7bca
--- /dev/null
+++ b/rust/usuba/src/bake/python.rs
@@ -0,0 +1,89 @@
+use async_trait::async_trait;
+use bytes::Bytes;
+use tempfile::TempDir;
+use tokio::{process::Command, task::JoinSet};
+
+use crate::{write_file, Bake};
+
+#[derive(Debug)]
+pub struct PythonBaker {}
+
+#[async_trait]
+impl Bake for PythonBaker {
+ #[instrument]
+ async fn bake(
+ &self,
+ world: &str,
+ wit: Vec,
+ source_code: Bytes,
+ library: Vec,
+ ) -> Result {
+ let workspace = TempDir::new()?;
+ debug!(
+ "Created temporary workspace in {}",
+ workspace.path().display()
+ );
+
+ let wasm_path = workspace.path().join("module.wasm");
+ let python_path = workspace.path().join("module.py");
+
+ debug!(?workspace, "Created temporary workspace");
+
+ let wit_path = workspace.path().join("wit");
+ let wit_deps_path = wit_path.join("deps");
+
+ tokio::fs::create_dir_all(&wit_deps_path).await?;
+
+ let mut writes = JoinSet::new();
+
+ wit.into_iter()
+ .enumerate()
+ .map(|(i, wit)| write_file(wit_path.join(format!("module{}.wit", i)), wit))
+ .chain([write_file(python_path.clone(), source_code)])
+ .chain(
+ library.into_iter().enumerate().map(|(i, wit)| {
+ write_file(wit_deps_path.join(format!("library{}.wit", i)), wit)
+ }),
+ )
+ .for_each(|fut| {
+ writes.spawn(fut);
+ });
+
+ while let Some(result) = writes.try_join_next() {
+ result??;
+ continue;
+ }
+
+ debug!(?workspace, "Populated temporary input files");
+
+ let mut command = Command::new("componentize-py");
+
+ command
+ .current_dir(workspace.path())
+ .arg("-d")
+ .arg(wit_path)
+ .arg("-w")
+ .arg(world)
+ .arg("componentize")
+ .arg("-p")
+ .arg(workspace.path().display().to_string())
+ .arg("-o")
+ .arg("module.wasm")
+ .arg("module");
+
+ let child = command.spawn()?;
+ let output = child.wait_with_output().await?;
+
+ if output.stderr.len() > 0 {
+ warn!("{}", String::from_utf8_lossy(&output.stderr));
+ }
+
+ debug!("Finished building with componentize-py");
+
+ let wasm_bytes = tokio::fs::read(&wasm_path).await?;
+
+ info!("Finished baking");
+
+ Ok(wasm_bytes.into())
+ }
+}
diff --git a/rust/usuba/src/bin/usuba.rs b/rust/usuba/src/bin/usuba.rs
index b5fb5e29a..15119b545 100644
--- a/rust/usuba/src/bin/usuba.rs
+++ b/rust/usuba/src/bin/usuba.rs
@@ -17,10 +17,16 @@ pub async fn main() -> Result<(), UsubaError> {
let port = std::option_env!("PORT").unwrap_or("8080");
let socket_address: SocketAddr = format!("0.0.0.0:{port}").parse()?;
let listener = tokio::net::TcpListener::bind(socket_address).await?;
+ let upstream = std::option_env!("UPSTREAM")
+ .map(|upstream| upstream.parse().ok())
+ .unwrap_or(None);
info!("Server listening on {}", socket_address);
+ if let Some(upstream) = &upstream {
+ info!("Reverse proxying requests to {}", upstream);
+ }
- serve(listener).await?;
+ serve(listener, upstream).await?;
Ok(())
}
diff --git a/rust/usuba/src/error.rs b/rust/usuba/src/error.rs
index eaaa76771..a2a03e50c 100644
--- a/rust/usuba/src/error.rs
+++ b/rust/usuba/src/error.rs
@@ -1,10 +1,16 @@
// use std::fmt::Display;
-use axum::{extract::multipart::MultipartError, http::StatusCode, response::IntoResponse, Json};
+use axum::{
+ extract::multipart::MultipartError,
+ http::{uri::InvalidUri, StatusCode},
+ response::IntoResponse,
+ Json,
+};
use blake3::HexError;
use redb::{CommitError, DatabaseError, StorageError, TableError, TransactionError};
use serde::{Deserialize, Serialize};
use thiserror::Error;
+use tokio::task::JoinError;
use tracing::subscriber::SetGlobalDefaultError;
use utoipa::ToSchema;
@@ -16,8 +22,12 @@ pub enum UsubaError {
BakeFailure(String),
#[error("Invalid configuration: {0}")]
InvalidConfiguration(String),
+ #[error("Invalid module: {0}")]
+ InvalidModule(String),
#[error("Module not found")]
ModuleNotFound,
+ #[error("Upstream request failed: {0}")]
+ UpstreamError(String),
#[error("An internal error occurred")]
Internal(String),
}
@@ -89,14 +99,43 @@ impl From for UsubaError {
}
}
+impl From for UsubaError {
+ fn from(value: JoinError) -> Self {
+ error!("{}", value);
+ UsubaError::Internal(format!("{}", value))
+ }
+}
+
+impl From for UsubaError {
+ fn from(value: anyhow::Error) -> Self {
+ error!("{}", value);
+ UsubaError::Internal(format!("{}", value))
+ }
+}
+
+impl From for UsubaError {
+ fn from(value: hyper_util::client::legacy::Error) -> Self {
+ UsubaError::UpstreamError(format!("{}", value))
+ }
+}
+
+impl From for UsubaError {
+ fn from(value: InvalidUri) -> Self {
+ warn!("{}", value);
+ UsubaError::BadRequest
+ }
+}
+
impl IntoResponse for UsubaError {
fn into_response(self) -> axum::response::Response {
let status = match self {
UsubaError::BadRequest => StatusCode::BAD_REQUEST,
+ UsubaError::InvalidModule(_) => StatusCode::BAD_REQUEST,
UsubaError::BakeFailure(_) => StatusCode::INTERNAL_SERVER_ERROR,
UsubaError::InvalidConfiguration(_) => StatusCode::BAD_REQUEST,
UsubaError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
UsubaError::ModuleNotFound => StatusCode::NOT_FOUND,
+ UsubaError::UpstreamError(_) => StatusCode::BAD_GATEWAY,
};
(
diff --git a/rust/usuba/src/routes/module/build.rs b/rust/usuba/src/routes/module/build.rs
index 518542758..182c9cbc8 100644
--- a/rust/usuba/src/routes/module/build.rs
+++ b/rust/usuba/src/routes/module/build.rs
@@ -8,12 +8,16 @@ use axum::{
use bytes::Bytes;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
+use wit_parser::UnresolvedPackage;
use crate::{Bake, Baker, HashStorage, UsubaError, UsubaState};
#[derive(ToSchema)]
+/// A `multipart/form-data` payload that consists of module WIT + source code as
+/// well as additional (optional) library WIT files
pub struct BuildModuleRequest {
- pub files: Vec>,
+ pub module: Vec>,
+ pub library: Vec>,
}
#[derive(Serialize, Deserialize, ToSchema)]
@@ -38,45 +42,75 @@ impl IntoResponse for BuildModuleResponse {
)
)]
pub async fn build_module(
- State(UsubaState { mut storage }): State,
+ State(UsubaState { mut storage, .. }): State,
mut form_data: Multipart,
) -> Result {
- let mut wit: Option = None;
+ let mut world_name: Option = None;
+ let mut wit: Vec = Vec::new();
+ let mut library: Vec = Vec::new();
let mut source_code: Option = None;
let mut baker: Option = None;
- 'collect_files: while let Some(field) = form_data.next_field().await? {
+ while let Some(field) = form_data.next_field().await? {
if let Some(file_name) = field.file_name() {
let file_name = PathBuf::from(file_name);
- if let Some(extension) = file_name.extension() {
- match extension.to_str() {
- Some("wit") => {
- wit = Some(field.bytes().await?);
- }
- Some("js") => {
- source_code = Some(field.bytes().await?);
- baker = Some(Baker::JavaScript);
- }
- _ => (),
- };
- }
- }
+ match field.name() {
+ Some("module") => {
+ if let Some(extension) = file_name.extension() {
+ match extension.to_str() {
+ Some("wit") => {
+ let module_wit = field.bytes().await?;
+ let wit_package = UnresolvedPackage::parse(
+ &PathBuf::from("module.wit"),
+ String::from_utf8_lossy(&module_wit).as_ref(),
+ )?;
- match (&wit, &source_code, &baker) {
- (Some(_), Some(_), Some(_)) => break 'collect_files,
- _ => (),
+ wit.push(module_wit);
+
+ world_name = Some(
+ wit_package
+ .worlds
+ .iter()
+ .nth(0)
+ .map(|(_, world)| world.name.clone())
+ .ok_or_else(|| {
+ UsubaError::InvalidModule(format!(
+ "Module WIT does not contain a world"
+ ))
+ })?,
+ );
+ }
+ Some("js") => {
+ source_code = Some(field.bytes().await?);
+ baker = Some(Baker::JavaScript);
+ }
+ Some("py") => {
+ source_code = Some(field.bytes().await?);
+ baker = Some(Baker::Python);
+ }
+ _ => (),
+ };
+ }
+ }
+ Some("library") => {
+ library.push(field.bytes().await?);
+ }
+ Some(name) => warn!("Unexpected multipart content: {name}"),
+ _ => warn!("Skipping unnamed multipart content"),
+ };
}
}
- if let (Some(wit), Some(source_code), Some(baker)) = (wit, source_code, baker) {
- let wasm = baker.bake(wit, source_code).await?;
+ if let (Some(world_name), Some(source_code), Some(baker)) = (world_name, source_code, baker) {
+ let wasm = baker.bake(&world_name, wit, source_code, library).await?;
let hash = storage.write(wasm).await?;
Ok(BuildModuleResponse {
id: hash.to_string(),
})
} else {
+ warn!("Insufficient payload inputs to build the module");
Err(UsubaError::BadRequest)
}
}
diff --git a/rust/usuba/src/routes/module/retrieve.rs b/rust/usuba/src/routes/module/retrieve.rs
index 94ff668ad..15d6791ae 100644
--- a/rust/usuba/src/routes/module/retrieve.rs
+++ b/rust/usuba/src/routes/module/retrieve.rs
@@ -15,7 +15,7 @@ use crate::{HashStorage, UsubaError, UsubaState};
)
)]
pub async fn retrieve_module(
- State(UsubaState { storage }): State,
+ State(UsubaState { storage, .. }): State,
Path((id,)): Path<(String,)>,
) -> Result {
let hash = Hash::from_str(&id)?;
diff --git a/rust/usuba/src/routes/ui.rs b/rust/usuba/src/routes/ui.rs
index fbd1b6f49..873ba0f29 100644
--- a/rust/usuba/src/routes/ui.rs
+++ b/rust/usuba/src/routes/ui.rs
@@ -1,9 +1,12 @@
use axum::{
+ extract::{Request, State},
http::{header, StatusCode, Uri},
response::{IntoResponse, Response},
};
use rust_embed::Embed;
+use crate::{UsubaError, UsubaState};
+
#[derive(Embed)]
#[folder = "../../typescript/packages/usuba-ui/dist"]
struct Asset;
@@ -27,11 +30,45 @@ where
}
}
-pub async fn ui_file(uri: Uri) -> impl IntoResponse {
+pub async fn ui_file(
+ uri: Uri,
+ State(UsubaState {
+ client, upstream, ..
+ }): State,
+ mut request: Request,
+) -> Result {
let path = uri.path().trim_start_matches('/').to_string();
- StaticFile(path)
+ let ui_response = StaticFile(path.clone()).into_response();
+
+ match (ui_response.status(), upstream) {
+ (StatusCode::NOT_FOUND, Some(upstream)) => {
+ *request.uri_mut() = Uri::try_from(format!(
+ "{}://{}/{}",
+ upstream
+ .scheme()
+ .map(|scheme| scheme.as_str())
+ .unwrap_or("http"),
+ upstream
+ .authority()
+ .map(|authority| authority.as_str())
+ .unwrap_or("localhost"),
+ path
+ ))?;
+
+ client
+ .request(request)
+ .await
+ .map(|response| response.into_response())
+ .map_err(|error| UsubaError::from(error))
+ }
+ _ => Ok(ui_response),
+ }
+}
+
+pub async fn upstream_index(state: State, request: Request) -> impl IntoResponse {
+ ui_file("/index.html".parse::().unwrap(), state, request).await
}
-pub async fn ui_index() -> impl IntoResponse {
- ui_file("/index.html".parse::().unwrap()).await
+pub async fn ui_index(state: State, request: Request) -> impl IntoResponse {
+ ui_file("/$.html".parse::().unwrap(), state, request).await
}
diff --git a/rust/usuba/src/serve.rs b/rust/usuba/src/serve.rs
index 929bb75a7..833d2c578 100644
--- a/rust/usuba/src/serve.rs
+++ b/rust/usuba/src/serve.rs
@@ -1,33 +1,59 @@
+use std::time::Duration;
+
use axum::{
+ body::Body,
+ http::{Method, Uri},
routing::{get, post},
Router,
};
+use hyper_util::{
+ client::legacy::{connect::HttpConnector, Client},
+ rt::TokioExecutor,
+};
use tokio::net::TcpListener;
+use tower_http::cors::{Any, CorsLayer};
use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi;
use crate::{
error::UsubaError,
openapi::OpenApiDocs,
- routes::{build_module, retrieve_module, ui_file, ui_index},
+ routes::{build_module, retrieve_module, ui_file, ui_index, upstream_index},
PersistedHashStorage,
};
+pub type HttpClient = hyper_util::client::legacy::Client;
+
#[derive(Clone)]
pub struct UsubaState {
pub storage: PersistedHashStorage,
+ pub client: HttpClient,
+ pub upstream: Option,
}
-pub async fn serve(listener: TcpListener) -> Result<(), UsubaError> {
+pub async fn serve(listener: TcpListener, upstream: Option) -> Result<(), UsubaError> {
let storage = PersistedHashStorage::temporary()?;
+ let client: HttpClient = Client::<(), ()>::builder(TokioExecutor::new())
+ .pool_idle_timeout(Duration::from_secs(30))
+ .build_http();
+
+ let cors = CorsLayer::new()
+ .allow_methods([Method::GET, Method::POST])
+ .allow_origin(Any);
let app = Router::new()
.merge(SwaggerUi::new("/swagger-ui").url("/openapi.json", OpenApiDocs::openapi()))
.route("/api/v0/module", post(build_module))
.route("/api/v0/module/:id", get(retrieve_module))
- .route("/", get(ui_index))
+ .route("/", get(upstream_index))
+ .route("/$", get(ui_index))
.route("/*file", get(ui_file))
- .with_state(UsubaState { storage });
+ .with_state(UsubaState {
+ storage,
+ client,
+ upstream,
+ })
+ .layer(cors);
axum::serve(listener, app.into_make_service()).await?;
diff --git a/typescript/package-lock.json b/typescript/package-lock.json
index ab156b71e..3798405cd 100644
--- a/typescript/package-lock.json
+++ b/typescript/package-lock.json
@@ -32,12 +32,64 @@
"url": "https://github.com/sponsors/philsturgeon"
}
},
+ "node_modules/@bytecodealliance/jco": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@bytecodealliance/jco/-/jco-1.2.4.tgz",
+ "integrity": "sha512-uuOm9UkYqWp5uElYDNzlhjbdrAmczEvETgQdI1hFTk79h+mrmHPRV32pgRP5o1eHVwMIpuk4XQkDIhFbksurUw==",
+ "dev": true,
+ "workspaces": [
+ "packages/preview2-shim"
+ ],
+ "dependencies": {
+ "@bytecodealliance/preview2-shim": "^0.16.2",
+ "binaryen": "^116.0.0",
+ "chalk-template": "^1",
+ "commander": "^12",
+ "mkdirp": "^3",
+ "ora": "^8",
+ "terser": "^5"
+ },
+ "bin": {
+ "jco": "src/jco.js"
+ }
+ },
+ "node_modules/@bytecodealliance/jco/node_modules/mkdirp": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
+ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
+ "dev": true,
+ "bin": {
+ "mkdirp": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/@bytecodealliance/preview2-shim": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@bytecodealliance/preview2-shim/-/preview2-shim-0.16.2.tgz",
"integrity": "sha512-36MwesmbLSf3Y5/OHcS85iBaF0N92CQ4gpjtDVKSbrjxmrBKCWlWVfoQ03F/cqDg8k5K7pzVaVBH0XBIbTCfTQ==",
"dev": true
},
+ "node_modules/@commontools/runtime-demo": {
+ "resolved": "packages/runtime-demo",
+ "link": true
+ },
+ "node_modules/@commontools/std": {
+ "resolved": "packages/std",
+ "link": true
+ },
+ "node_modules/@commontools/usuba-api": {
+ "resolved": "packages/usuba-api",
+ "link": true
+ },
+ "node_modules/@commontools/usuba-rt": {
+ "resolved": "packages/usuba-rt",
+ "link": true
+ },
"node_modules/@commontools/usuba-sw": {
"resolved": "packages/usuba-sw",
"link": true
@@ -114,6 +166,64 @@
"typescript": "^5.x"
}
},
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
"node_modules/@jsdevtools/ono": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
@@ -289,6 +399,18 @@
"node": ">=0.4.0"
}
},
+ "node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
@@ -320,6 +442,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/binaryen": {
+ "version": "116.0.0",
+ "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-116.0.0.tgz",
+ "integrity": "sha512-Hp0dXC6Cb/rTwWEoUS2BRghObE7g/S9umKtxuTDt3f61G6fNTE/YVew/ezyy3IdHcLx3f17qfh6LwETgCfvWkQ==",
+ "dev": true,
+ "bin": {
+ "wasm-opt": "bin/wasm-opt",
+ "wasm2js": "bin/wasm2js"
+ }
+ },
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -332,6 +464,12 @@
"node": ">=8"
}
},
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
"node_modules/c12": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/c12/-/c12-1.10.0.tgz",
@@ -364,6 +502,33 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "dev": true,
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk-template": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz",
+ "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk-template?sponsor=1"
+ }
+ },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -406,6 +571,33 @@
"consola": "^3.2.3"
}
},
+ "node_modules/cli-cursor": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
+ "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
+ "dev": true,
+ "dependencies": {
+ "restore-cursor": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/commander": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
@@ -479,6 +671,12 @@
"url": "https://dotenvx.com"
}
},
+ "node_modules/emoji-regex": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
+ "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==",
+ "dev": true
+ },
"node_modules/esbuild": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
@@ -517,10 +715,6 @@
"@esbuild/win32-x64": "0.20.2"
}
},
- "node_modules/example-package": {
- "resolved": "packages/example-package",
- "link": true
- },
"node_modules/execa": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
@@ -617,6 +811,18 @@
"node": ">=8"
}
},
+ "node_modules/get-east-asian-width": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz",
+ "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/get-stream": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
@@ -729,6 +935,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-interactive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
+ "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -750,6 +968,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/is-unicode-supported": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz",
+ "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -811,6 +1041,34 @@
"@types/trusted-types": "^2.0.2"
}
},
+ "node_modules/log-symbols": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz",
+ "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^5.3.0",
+ "is-unicode-supported": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/is-unicode-supported": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
+ "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -1024,6 +1282,29 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/ora": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz",
+ "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^5.3.0",
+ "cli-cursor": "^4.0.0",
+ "cli-spinners": "^2.9.2",
+ "is-interactive": "^2.0.0",
+ "is-unicode-supported": "^2.0.0",
+ "log-symbols": "^6.0.0",
+ "stdin-discarder": "^0.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -1160,6 +1441,46 @@
"node": ">=8.10.0"
}
},
+ "node_modules/restore-cursor": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
+ "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
+ "dev": true,
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/retry": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
@@ -1282,6 +1603,60 @@
"node": ">=0.10.0"
}
},
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/stdin-discarder": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz",
+ "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz",
+ "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
"node_modules/strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
@@ -1311,6 +1686,30 @@
"node": ">=10"
}
},
+ "node_modules/terser": {
+ "version": "5.31.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz",
+ "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -1323,6 +1722,12 @@
"node": ">=8.0"
}
},
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
"node_modules/typescript": {
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
@@ -1462,6 +1867,7 @@
},
"packages/example-package": {
"version": "0.0.1",
+ "extraneous": true,
"license": "UNLICENSED",
"devDependencies": {
"@bytecodealliance/preview2-shim": "^0.16.2",
@@ -1470,10 +1876,58 @@
"wireit": "^0.14.4"
}
},
+ "packages/runtime-demo": {
+ "name": "@commontools/runtime-demo",
+ "version": "0.0.1",
+ "license": "UNLICENSED",
+ "devDependencies": {
+ "@commontools/usuba-rt": "^0.0.1",
+ "@shoelace-style/shoelace": "^2.15.1",
+ "typescript": "^5.2.2",
+ "vite": "^5.2.0",
+ "wireit": "^0.14.4"
+ }
+ },
+ "packages/std": {
+ "name": "@commontools/std",
+ "version": "0.0.1",
+ "license": "UNLICENSED",
+ "devDependencies": {
+ "@bytecodealliance/jco": "^1.2.4",
+ "typescript": "^5.2.2",
+ "wireit": "^0.14.4"
+ }
+ },
+ "packages/usuba-api": {
+ "name": "@commontools/usuba-api",
+ "version": "0.0.1",
+ "license": "UNLICENSED",
+ "devDependencies": {
+ "@hey-api/openapi-ts": "^0.46.0",
+ "typescript": "^5.2.2",
+ "wireit": "^0.14.4"
+ }
+ },
+ "packages/usuba-rt": {
+ "name": "@commontools/usuba-rt",
+ "version": "0.0.1",
+ "license": "UNLICENSED",
+ "dependencies": {
+ "@commontools/usuba-api": "^0.0.1"
+ },
+ "devDependencies": {
+ "tslib": "^2.6.2",
+ "typescript": "^5.2.2",
+ "wireit": "^0.14.4"
+ }
+ },
"packages/usuba-sw": {
"name": "@commontools/usuba-sw",
"version": "0.0.1",
"license": "UNLICENSED",
+ "dependencies": {
+ "@commontools/usuba-api": "^0.0.1"
+ },
"devDependencies": {
"@bytecodealliance/preview2-shim": "^0.16.2",
"@hey-api/openapi-ts": "^0.46.0",
@@ -1491,6 +1945,7 @@
"@shoelace-style/shoelace": "^2.15.1"
},
"devDependencies": {
+ "@commontools/usuba-api": "^0.0.1",
"@commontools/usuba-sw": "^0.0.1",
"typescript": "^5.2.2",
"vite": "^5.2.0",
diff --git a/typescript/package.json b/typescript/package.json
index fd257608b..d5aab8573 100644
--- a/typescript/package.json
+++ b/typescript/package.json
@@ -10,7 +10,8 @@
"./packages/*"
],
"scripts": {
- "build": "wireit"
+ "build": "wireit",
+ "clean": "wireit"
},
"repository": {
"type": "git",
@@ -26,10 +27,19 @@
"wireit": {
"build": {
"dependencies": [
- "./packages/example-package:build",
+ "./packages/usuba-rt:build",
+ "./packages/usuba-api:build",
"./packages/usuba-sw:build",
"./packages/usuba-ui:build"
]
+ },
+ "clean": {
+ "dependencies": [
+ "./packages/usuba-rt:clean",
+ "./packages/usuba-api:clean",
+ "./packages/usuba-sw:clean",
+ "./packages/usuba-ui:clean"
+ ]
}
}
-}
\ No newline at end of file
+}
diff --git a/typescript/packages/example-package/index.html b/typescript/packages/example-package/index.html
deleted file mode 100644
index e73947fd4..000000000
--- a/typescript/packages/example-package/index.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
- Cowsayer Web
-
-
-
-
-
-
- Vite + Lit
-
-
-
-
\ No newline at end of file
diff --git a/typescript/packages/example-package/package-lock.json b/typescript/packages/example-package/package-lock.json
deleted file mode 100644
index 0c658987d..000000000
--- a/typescript/packages/example-package/package-lock.json
+++ /dev/null
@@ -1,1313 +0,0 @@
-{
- "name": "example-package",
- "version": "0.0.1",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "example-package",
- "version": "0.0.1",
- "license": "UNLICENSED",
- "dependencies": {
- "@bytecodealliance/preview2-shim": "^0.16.2",
- "typescript": "^5.2.2",
- "vite": "^5.2.0"
- },
- "devDependencies": {
- "@rollup/plugin-node-resolve": "^15.2.3",
- "wireit": "^0.14.4"
- }
- },
- "node_modules/@bytecodealliance/preview2-shim": {
- "version": "0.16.2",
- "resolved": "https://registry.npmjs.org/@bytecodealliance/preview2-shim/-/preview2-shim-0.16.2.tgz",
- "integrity": "sha512-36MwesmbLSf3Y5/OHcS85iBaF0N92CQ4gpjtDVKSbrjxmrBKCWlWVfoQ03F/cqDg8k5K7pzVaVBH0XBIbTCfTQ=="
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
- "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
- "cpu": [
- "ppc64"
- ],
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
- "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
- "cpu": [
- "arm"
- ],
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
- "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
- "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
- "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
- "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
- "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
- "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
- "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
- "cpu": [
- "arm"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
- "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
- "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
- "cpu": [
- "ia32"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
- "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
- "cpu": [
- "loong64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
- "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
- "cpu": [
- "mips64el"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
- "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
- "cpu": [
- "ppc64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
- "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
- "cpu": [
- "riscv64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
- "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
- "cpu": [
- "s390x"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
- "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
- "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
- "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
- "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
- "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
- "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
- "cpu": [
- "ia32"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
- "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@rollup/plugin-node-resolve": {
- "version": "15.2.3",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz",
- "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==",
- "dev": true,
- "dependencies": {
- "@rollup/pluginutils": "^5.0.1",
- "@types/resolve": "1.20.2",
- "deepmerge": "^4.2.2",
- "is-builtin-module": "^3.2.1",
- "is-module": "^1.0.0",
- "resolve": "^1.22.1"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "rollup": "^2.78.0||^3.0.0||^4.0.0"
- },
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
- }
- }
- },
- "node_modules/@rollup/pluginutils": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
- "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
- "dev": true,
- "dependencies": {
- "@types/estree": "^1.0.0",
- "estree-walker": "^2.0.2",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
- },
- "peerDependenciesMeta": {
- "rollup": {
- "optional": true
- }
- }
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
- "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==",
- "cpu": [
- "arm"
- ],
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz",
- "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz",
- "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz",
- "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz",
- "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==",
- "cpu": [
- "arm"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz",
- "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==",
- "cpu": [
- "arm"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz",
- "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz",
- "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz",
- "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==",
- "cpu": [
- "ppc64"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz",
- "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==",
- "cpu": [
- "riscv64"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz",
- "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==",
- "cpu": [
- "s390x"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz",
- "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz",
- "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz",
- "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz",
- "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==",
- "cpu": [
- "ia32"
- ],
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz",
- "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@types/estree": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
- "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
- },
- "node_modules/@types/resolve": {
- "version": "1.20.2",
- "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
- "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
- "dev": true
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "dependencies": {
- "fill-range": "^7.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/builtin-modules": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
- "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
- "dev": true,
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dev": true,
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/esbuild": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
- "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.20.2",
- "@esbuild/android-arm": "0.20.2",
- "@esbuild/android-arm64": "0.20.2",
- "@esbuild/android-x64": "0.20.2",
- "@esbuild/darwin-arm64": "0.20.2",
- "@esbuild/darwin-x64": "0.20.2",
- "@esbuild/freebsd-arm64": "0.20.2",
- "@esbuild/freebsd-x64": "0.20.2",
- "@esbuild/linux-arm": "0.20.2",
- "@esbuild/linux-arm64": "0.20.2",
- "@esbuild/linux-ia32": "0.20.2",
- "@esbuild/linux-loong64": "0.20.2",
- "@esbuild/linux-mips64el": "0.20.2",
- "@esbuild/linux-ppc64": "0.20.2",
- "@esbuild/linux-riscv64": "0.20.2",
- "@esbuild/linux-s390x": "0.20.2",
- "@esbuild/linux-x64": "0.20.2",
- "@esbuild/netbsd-x64": "0.20.2",
- "@esbuild/openbsd-x64": "0.20.2",
- "@esbuild/sunos-x64": "0.20.2",
- "@esbuild/win32-arm64": "0.20.2",
- "@esbuild/win32-ia32": "0.20.2",
- "@esbuild/win32-x64": "0.20.2"
- }
- },
- "node_modules/estree-walker": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
- "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
- "dev": true
- },
- "node_modules/fast-glob": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fastq": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
- "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-builtin-module": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
- "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
- "dev": true,
- "dependencies": {
- "builtin-modules": "^3.3.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.13.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
- "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
- "dev": true,
- "dependencies": {
- "hasown": "^2.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
- "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
- "dev": true
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/jsonc-parser": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
- "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
- "dev": true
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.38",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.7",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.2.0"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/proper-lockfile": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz",
- "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "retry": "^0.12.0",
- "signal-exit": "^3.0.2"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.8",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
- "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.13.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/rollup": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz",
- "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==",
- "dependencies": {
- "@types/estree": "1.0.5"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.17.2",
- "@rollup/rollup-android-arm64": "4.17.2",
- "@rollup/rollup-darwin-arm64": "4.17.2",
- "@rollup/rollup-darwin-x64": "4.17.2",
- "@rollup/rollup-linux-arm-gnueabihf": "4.17.2",
- "@rollup/rollup-linux-arm-musleabihf": "4.17.2",
- "@rollup/rollup-linux-arm64-gnu": "4.17.2",
- "@rollup/rollup-linux-arm64-musl": "4.17.2",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2",
- "@rollup/rollup-linux-riscv64-gnu": "4.17.2",
- "@rollup/rollup-linux-s390x-gnu": "4.17.2",
- "@rollup/rollup-linux-x64-gnu": "4.17.2",
- "@rollup/rollup-linux-x64-musl": "4.17.2",
- "@rollup/rollup-win32-arm64-msvc": "4.17.2",
- "@rollup/rollup-win32-ia32-msvc": "4.17.2",
- "@rollup/rollup-win32-x64-msvc": "4.17.2",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
- },
- "node_modules/source-map-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/typescript": {
- "version": "5.4.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
- "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/vite": {
- "version": "5.2.11",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
- "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==",
- "dependencies": {
- "esbuild": "^0.20.1",
- "postcss": "^8.4.38",
- "rollup": "^4.13.0"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || >=20.0.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/wireit": {
- "version": "0.14.4",
- "resolved": "https://registry.npmjs.org/wireit/-/wireit-0.14.4.tgz",
- "integrity": "sha512-WNAXEw2cJs1nSRNJNRcPypARZNumgtsRTJFTNpd6turCA6JZ6cEwl4ZU3C1IHc/3IaXoPu9LdxcI5TBTdD6/pg==",
- "dev": true,
- "workspaces": [
- "vscode-extension",
- "website"
- ],
- "dependencies": {
- "braces": "^3.0.2",
- "chokidar": "^3.5.3",
- "fast-glob": "^3.2.11",
- "jsonc-parser": "^3.0.0",
- "proper-lockfile": "^4.1.2"
- },
- "bin": {
- "wireit": "bin/wireit.js"
- },
- "engines": {
- "node": ">=14.14.0"
- }
- }
- }
-}
diff --git a/typescript/packages/example-package/package.json b/typescript/packages/example-package/package.json
deleted file mode 100644
index 9d6e5bf34..000000000
--- a/typescript/packages/example-package/package.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "name": "example-package",
- "author": "The Common Authors",
- "version": "0.0.1",
- "description": "An example TypeScript + Wasm package for web, Deno and Node.js",
- "license": "UNLICENSED",
- "private": true,
- "type": "module",
- "scripts": {
- "build": "wireit",
- "deno": "wireit",
- "serve": "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",
- "devDependencies": {
- "@bytecodealliance/preview2-shim": "^0.16.2",
- "typescript": "^5.2.2",
- "vite": "^5.2.0",
- "wireit": "^0.14.4"
- },
- "wireit": {
- "build:wasm": {
- "command": "../../../rust/example-crate/build-wasm-component.sh",
- "files": [
- "../../../rust/**/*.rs"
- ],
- "output": [
- "./src/cowsayer-wasm/**"
- ]
- },
- "build": {
- "command": "tsc && vite build",
- "dependencies": [
- "build:wasm"
- ]
- },
- "serve": {
- "command": "vite",
- "service": true
- },
- "preview": {
- "command": "vite preview"
- },
- "deno": {
- "command": "deno run -q --allow-env --allow-read ./src/cowsayer.ts"
- }
- }
-}
\ No newline at end of file
diff --git a/typescript/packages/example-package/src/cowsayer-wasm b/typescript/packages/example-package/src/cowsayer-wasm
deleted file mode 120000
index 5834d5522..000000000
--- a/typescript/packages/example-package/src/cowsayer-wasm
+++ /dev/null
@@ -1 +0,0 @@
-../../../../target/wasm32-wasi/release/example_component_package
\ No newline at end of file
diff --git a/typescript/packages/example-package/src/cowsayer.ts b/typescript/packages/example-package/src/cowsayer.ts
deleted file mode 100644
index dd361fdd7..000000000
--- a/typescript/packages/example-package/src/cowsayer.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { cow } from './cowsayer-wasm/example_component.js';
-
-const cowSays = cow.say('moo', undefined);
-const owlSays = cow.say('hoo', 'owl');
-
-if (typeof document !== 'undefined') {
- document.documentElement.innerHTML = `
-
-
-${cowSays}
-
-
-
-
-
-${owlSays}
-
-
`;
-} else {
- console.log(cowSays);
- console.log(owlSays);
-}
diff --git a/typescript/packages/example-package/tsconfig.json b/typescript/packages/example-package/tsconfig.json
deleted file mode 100644
index efa6bfdf2..000000000
--- a/typescript/packages/example-package/tsconfig.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "compilerOptions": {
- "target": "ES2020",
- "experimentalDecorators": true,
- "useDefineForClassFields": false,
- "module": "ESNext",
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
- "skipLibCheck": false,
-
- /* Bundler mode */
- "moduleResolution": "node",
- "allowImportingTsExtensions": true,
- "resolveJsonModule": true,
- "isolatedModules": true,
- "noEmit": true,
-
- /* Linting */
- "strict": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "noFallthroughCasesInSwitch": true
- },
- "include": [
- "src",
- "node_modules/@bytecodealliance"
- ]
-}
diff --git a/typescript/packages/example-package/vite.config.js b/typescript/packages/example-package/vite.config.js
deleted file mode 100644
index 216a2f1bb..000000000
--- a/typescript/packages/example-package/vite.config.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
- build: {
- target: 'esnext'
- },
- resolve: {
- preserveSymlinks: true
- }
-};
\ No newline at end of file
diff --git a/typescript/packages/runtime-demo/index.html b/typescript/packages/runtime-demo/index.html
new file mode 100644
index 000000000..cc8e35529
--- /dev/null
+++ b/typescript/packages/runtime-demo/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ Runtime Sandbox
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/typescript/packages/runtime-demo/package.json b/typescript/packages/runtime-demo/package.json
new file mode 100644
index 000000000..0dbfcf435
--- /dev/null
+++ b/typescript/packages/runtime-demo/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "@commontools/runtime-demo",
+ "author": "The Common Authors",
+ "version": "0.0.1",
+ "description": "Testbed for usuba-rt",
+ "license": "UNLICENSED",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "wireit",
+ "clean": "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",
+ "devDependencies": {
+ "@commontools/usuba-rt": "^0.0.1",
+ "@shoelace-style/shoelace": "^2.15.1",
+ "typescript": "^5.2.2",
+ "vite": "^5.2.0",
+ "wireit": "^0.14.4"
+ },
+ "wireit": {
+ "build": {
+ "dependencies": [
+ "../usuba-rt:build"
+ ],
+ "command": "vite build"
+ },
+ "clean": {
+ "command": "rm -rf ./lib ./dist ./.wireit"
+ }
+ }
+}
\ No newline at end of file
diff --git a/typescript/packages/runtime-demo/public/shoelace b/typescript/packages/runtime-demo/public/shoelace
new file mode 120000
index 000000000..07a2f6e41
--- /dev/null
+++ b/typescript/packages/runtime-demo/public/shoelace
@@ -0,0 +1 @@
+../../../node_modules/@shoelace-style/shoelace
\ No newline at end of file
diff --git a/typescript/packages/usuba-ui/public/styles.css b/typescript/packages/runtime-demo/public/styles.css
similarity index 100%
rename from typescript/packages/usuba-ui/public/styles.css
rename to typescript/packages/runtime-demo/public/styles.css
diff --git a/typescript/packages/runtime-demo/src/demo1.ts b/typescript/packages/runtime-demo/src/demo1.ts
new file mode 100644
index 000000000..955215862
--- /dev/null
+++ b/typescript/packages/runtime-demo/src/demo1.ts
@@ -0,0 +1,80 @@
+import { Runtime } from '@commontools/usuba-rt';
+
+export const COMMON_DIRECTORY_WIT = `
+package common:directory;
+
+interface lookup {
+ entry: func(index: u32) -> string;
+}
+
+world directory {
+ export lookup;
+}`;
+
+export const EXAMPLE_HELLO_WIT = `
+package example:hello;
+
+world hello {
+ import common:directory/lookup;
+
+ export hello: func() -> string;
+}`;
+
+export const EXAMPLE_HELLO_JS = `
+import { entry } from 'common:directory/lookup';
+
+export function hello() {
+ let value = entry(Math.floor(Math.random() * 10));
+ return 'Hello, Agent ' + value;
+}`;
+
+export const demo = async () => {
+ console.log('Initializing Runtime');
+
+ const rt = new Runtime([COMMON_DIRECTORY_WIT]);
+
+ console.log('Defining Module');
+
+ type ExpectedExports = {
+ hello: () => string;
+ };
+
+ const module = await rt.defineModule({
+ contentType: 'text/javascript',
+ wit: EXAMPLE_HELLO_WIT,
+ sourceCode: EXAMPLE_HELLO_JS,
+ });
+
+ console.log('Instantiating Module');
+
+ const agents = [
+ 'Marnie',
+ 'Orange',
+ 'Frank',
+ 'Moon',
+ 'Sparrow',
+ 'River',
+ 'Archer',
+ 'Bard',
+ 'Helman',
+ 'Poisson',
+ ];
+
+ const { hello } = await module.instantiate({
+ 'common:directory/lookup': {
+ entry(index: number) {
+ return agents[Math.floor(index) % 10];
+ },
+ },
+ });
+
+ console.log('Invoking Module API:');
+
+ console.log(`%c${hello()}`, 'font-size: 1.5em; font-weight: bold;');
+
+ (self as any).demos ||= {};
+ (self as any).demos.one = {
+ hello,
+ };
+ console.log('fin');
+};
diff --git a/typescript/packages/runtime-demo/src/demo2.ts b/typescript/packages/runtime-demo/src/demo2.ts
new file mode 100644
index 000000000..d79398f03
--- /dev/null
+++ b/typescript/packages/runtime-demo/src/demo2.ts
@@ -0,0 +1,131 @@
+import { Runtime } from '@commontools/usuba-rt';
+
+export const COMMON_ITERATOR_WIT = `
+package common:iterator;
+
+interface iterator {
+ variant value {
+ %string(string),
+ number(f64),
+ boolean(bool),
+ buffer(list)
+ }
+
+ resource iterable {
+ next: func() -> option;
+ value: func() -> option;
+ }
+
+ create: func() -> iterable;
+}
+
+world common {
+ export iterator;
+}`;
+
+export const USER_MODULE_JS = `
+class Iterable {
+ #iter;
+ #value;
+
+ constructor(iter) {
+ this.#iter = iter;
+ this.#value = iter.next();
+ }
+
+ next() {
+ this.#value = this.#iter.next();
+ if (this.#value.done) {
+ return;
+ }
+ return this;
+ }
+
+ value() {
+ return {
+ tag: 'number',
+ val: this.#value.value
+ };
+ }
+}
+
+function *doWork() {
+ for (let i = 0; i < 10; ++i) {
+ yield i;
+ }
+}
+
+export const iterator = {
+ Iterable,
+ create() {
+ const i = new Iterable(doWork());
+ console.log('Doing work', i);
+ return new Iterable(doWork());
+ }
+};`;
+
+export const demo = async () => {
+ console.log('Initializing Runtime');
+
+ const rt = new Runtime([]);
+
+ console.log('Defining Module');
+
+ type Value =
+ | {
+ tag: 'number';
+ val: number;
+ }
+ | {
+ tag: 'string';
+ val: string;
+ }
+ | {
+ tag: 'boolean';
+ val: boolean;
+ }
+ | {
+ tag: 'buffer';
+ val: Uint8Array;
+ };
+ interface Iterator {
+ next(): Iterator | void;
+ value(): Value | void;
+ }
+ type ExpectedExports = {
+ iterator: {
+ create: () => Iterator;
+ };
+ };
+
+ const module = await rt.defineModule({
+ contentType: 'text/javascript',
+ wit: COMMON_ITERATOR_WIT,
+ sourceCode: USER_MODULE_JS,
+ });
+
+ console.log('Instantiating Module');
+
+ const {
+ iterator: { create: createIterator },
+ } = await module.instantiate({});
+
+ console.log('Invoking Module API:');
+
+ for (
+ let iterator: Iterator | void = createIterator();
+ iterator;
+ iterator = iterator.next()
+ ) {
+ console.log(
+ `%cValue: ${iterator?.value()?.val}`,
+ 'font-size: 1.5em; font-weight: bold;'
+ );
+ }
+
+ (self as any).demos ||= {};
+ (self as any).demos.four = {
+ createIterator,
+ };
+ console.log('fin');
+};
diff --git a/typescript/packages/runtime-demo/src/demo3.ts b/typescript/packages/runtime-demo/src/demo3.ts
new file mode 100644
index 000000000..8eb83ff92
--- /dev/null
+++ b/typescript/packages/runtime-demo/src/demo3.ts
@@ -0,0 +1,76 @@
+import { Runtime } from '@commontools/usuba-rt';
+import {
+ COMMON_DIRECTORY_WIT,
+ EXAMPLE_HELLO_WIT,
+ EXAMPLE_HELLO_JS,
+} from './demo1.js';
+
+export const COMMON_DIRECTORY_JS = `
+const agents = [
+ 'Marnie',
+ 'Orange',
+ 'Frank',
+ 'Moon',
+ 'Sparrow',
+ 'River',
+ 'Archer',
+ 'Bard',
+ 'Helman',
+ 'Poisson',
+];
+
+export const lookup = {
+ entry: (index) => agents[Math.floor(Math.random() * agents.length)]
+};
+`;
+
+export const demo = async () => {
+ console.log('Initializing first Runtime');
+
+ const rtOne = new Runtime([]);
+
+ console.log('Defining first Module');
+
+ type ExpectedExportsOne = {
+ lookup: {
+ entry(index: number): string;
+ };
+ };
+
+ const moduleOne = await rtOne.defineModule({
+ contentType: 'text/javascript',
+ wit: COMMON_DIRECTORY_WIT,
+ sourceCode: COMMON_DIRECTORY_JS,
+ });
+
+ const rtTwo = new Runtime([COMMON_DIRECTORY_WIT]);
+
+ console.log('Defining second Module');
+
+ type ExpectedExportsTwo = {
+ hello: () => string;
+ };
+
+ const moduleTwo = await rtTwo.defineModule({
+ contentType: 'text/javascript',
+ wit: EXAMPLE_HELLO_WIT,
+ sourceCode: EXAMPLE_HELLO_JS,
+ });
+
+ console.log('Instantiating both Modules');
+
+ const { hello } = await moduleTwo.instantiate({
+ 'common:directory/lookup': (await moduleOne.instantiate({})).lookup,
+ });
+
+ console.log('Invoking final Module API:');
+
+ console.log(`%c${hello()}`, 'font-size: 1.5em; font-weight: bold;');
+
+ (self as any).demos ||= {};
+ (self as any).demos.two = {
+ hello,
+ };
+
+ console.log('fin');
+};
diff --git a/typescript/packages/runtime-demo/src/demo4.ts b/typescript/packages/runtime-demo/src/demo4.ts
new file mode 100644
index 000000000..096700c1c
--- /dev/null
+++ b/typescript/packages/runtime-demo/src/demo4.ts
@@ -0,0 +1,62 @@
+import { Runtime } from '@commontools/usuba-rt';
+import { COMMON_DIRECTORY_WIT, EXAMPLE_HELLO_WIT } from './demo1.js';
+import { COMMON_DIRECTORY_JS } from './demo3.js';
+
+export const EXAMPLE_HELLO_PY = `
+import random
+import hello
+from hello.imports import lookup
+
+class Hello(hello.Hello):
+ def hello(self) -> str:
+ return "Hello, Agent %s!" % lookup.entry(random.randint(0, 9))
+`;
+
+export const demo = async () => {
+ console.log('Initializing first Runtime');
+
+ const rtOne = new Runtime([]);
+
+ console.log('Defining first Module');
+
+ type ExpectedExportsOne = {
+ lookup: {
+ entry(index: number): string;
+ };
+ };
+
+ const moduleOne = await rtOne.defineModule({
+ contentType: 'text/javascript',
+ wit: COMMON_DIRECTORY_WIT,
+ sourceCode: COMMON_DIRECTORY_JS,
+ });
+
+ const rtTwo = new Runtime([COMMON_DIRECTORY_WIT]);
+
+ console.log('Defining second Module');
+
+ type ExpectedExportsTwo = {
+ hello: () => string;
+ };
+
+ const moduleTwo = await rtTwo.defineModule({
+ contentType: 'text/x-python',
+ wit: EXAMPLE_HELLO_WIT,
+ sourceCode: EXAMPLE_HELLO_PY,
+ });
+
+ console.log('Instantiating both Modules');
+
+ const { hello } = await moduleTwo.instantiate({
+ 'common:directory/lookup': (await moduleOne.instantiate({})).lookup,
+ });
+
+ console.log('Invoking final Module API:');
+
+ console.log(`%c${hello()}`, 'font-size: 1.5em; font-weight: bold;');
+ (self as any).demos ||= {};
+ (self as any).demos.three = {
+ hello,
+ };
+ console.log('fin');
+};
diff --git a/typescript/packages/runtime-demo/src/index.ts b/typescript/packages/runtime-demo/src/index.ts
new file mode 100644
index 000000000..886cb67fc
--- /dev/null
+++ b/typescript/packages/runtime-demo/src/index.ts
@@ -0,0 +1,9 @@
+import { demo as demoOne } from './demo1.js';
+import { demo as demoTwo } from './demo2.js';
+import { demo as demoThree } from './demo3.js';
+import { demo as demoFour } from './demo4.js';
+
+(self as any).demoOne = demoOne;
+(self as any).demoTwo = demoTwo;
+(self as any).demoThree = demoThree;
+(self as any).demoFour = demoFour;
diff --git a/typescript/packages/runtime-demo/tsconfig.json b/typescript/packages/runtime-demo/tsconfig.json
new file mode 100644
index 000000000..df767e62f
--- /dev/null
+++ b/typescript/packages/runtime-demo/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "lib": ["es2022", "DOM"],
+ "outDir": "./lib",
+ "rootDir": "./src",
+ },
+ "include": [
+ "src/**/*"
+ ]
+}
diff --git a/typescript/packages/runtime-demo/vite.config.js b/typescript/packages/runtime-demo/vite.config.js
new file mode 100644
index 000000000..edb6fa879
--- /dev/null
+++ b/typescript/packages/runtime-demo/vite.config.js
@@ -0,0 +1,12 @@
+// vite.config.js
+import { resolve } from 'path'
+import { defineConfig } from 'vite'
+
+export default defineConfig({
+ build: {
+ target: 'esnext'
+ },
+ resolve: {
+ preserveSymlinks: true
+ }
+})
\ No newline at end of file
diff --git a/typescript/packages/usuba-api/.gitignore b/typescript/packages/usuba-api/.gitignore
new file mode 100644
index 000000000..eb5155b41
--- /dev/null
+++ b/typescript/packages/usuba-api/.gitignore
@@ -0,0 +1,2 @@
+openapi-client
+lib
diff --git a/typescript/packages/usuba-api/openapi.json b/typescript/packages/usuba-api/openapi.json
new file mode 100644
index 000000000..5c840421b
--- /dev/null
+++ b/typescript/packages/usuba-api/openapi.json
@@ -0,0 +1,154 @@
+{
+ "openapi": "3.0.3",
+ "info": {
+ "title": "usuba",
+ "description": "An anything-to-Common-Wasm build server",
+ "license": {
+ "name": ""
+ },
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/api/v0/module": {
+ "post": {
+ "tags": [
+ "crate::routes"
+ ],
+ "operationId": "build_module",
+ "requestBody": {
+ "content": {
+ "multipart/form-data": {
+ "schema": {
+ "$ref": "#/components/schemas/BuildModuleRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "description": "Successfully built the module",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/BuildModuleResponse"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad request body",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/v0/module/{id}": {
+ "get": {
+ "tags": [
+ "crate::routes"
+ ],
+ "operationId": "retrieve_module",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successfully retrieved the module",
+ "content": {
+ "application/octet-stream": {
+ "schema": {
+ "type": "string",
+ "format": "binary"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Module not found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "BuildModuleRequest": {
+ "type": "object",
+ "description": "A `multipart/form-data` payload that consists of module WIT + source code as\nwell as additional (optional) library WIT files",
+ "required": [
+ "module",
+ "library"
+ ],
+ "properties": {
+ "library": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "binary"
+ }
+ },
+ "module": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "binary"
+ }
+ }
+ }
+ },
+ "BuildModuleResponse": {
+ "type": "object",
+ "required": [
+ "id"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ }
+ }
+ },
+ "ErrorResponse": {
+ "type": "object",
+ "required": [
+ "error"
+ ],
+ "properties": {
+ "error": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/typescript/packages/usuba-api/package.json b/typescript/packages/usuba-api/package.json
new file mode 100644
index 000000000..f78329074
--- /dev/null
+++ b/typescript/packages/usuba-api/package.json
@@ -0,0 +1,67 @@
+{
+ "name": "@commontools/usuba-api",
+ "author": "The Common Authors",
+ "version": "0.0.1",
+ "description": "Auto-generated REST API client for the Usuba build server",
+ "license": "UNLICENSED",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "wireit",
+ "clean": "wireit",
+ "update-openapi-spec": "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",
+ "files": [
+ "./lib/**/*"
+ ],
+ "exports": "./lib/index.js",
+ "devDependencies": {
+ "@hey-api/openapi-ts": "^0.46.0",
+ "typescript": "^5.2.2",
+ "wireit": "^0.14.4"
+ },
+ "wireit": {
+ "update-openapi-spec": {
+ "command": "./scripts/update-openapi-spec.sh",
+ "files": [
+ "./scripts/update-openapi-spec.sh"
+ ],
+ "output": [
+ "./openapi.json"
+ ]
+ },
+ "build:openapi-client": {
+ "command": "npx @hey-api/openapi-ts -i ./openapi.json -o ./src/openapi-client && ./scripts/fix-paths.sh",
+ "files": [
+ "./scripts/fix-paths.sh",
+ "./openapi.json"
+ ],
+ "output": [
+ "./src/openapi-client/**/*"
+ ]
+ },
+ "build": {
+ "dependencies": [
+ "build:openapi-client"
+ ],
+ "files": [
+ "./src/**/*"
+ ],
+ "output": [
+ "./lib/**/*"
+ ],
+ "command": "tsc --build -f"
+ },
+ "clean": {
+ "command": "rm -rf ./lib ./.wireit"
+ }
+ }
+}
\ No newline at end of file
diff --git a/typescript/packages/usuba-api/scripts/fix-paths.sh b/typescript/packages/usuba-api/scripts/fix-paths.sh
new file mode 100755
index 000000000..348a002eb
--- /dev/null
+++ b/typescript/packages/usuba-api/scripts/fix-paths.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+# The autogenerated REST client has module specifiers that omit their `.js`
+# extensions, which means they are incompatible with TypeScript's NodeNext
+# module resolution. Since the code is autogenerated anyway, we post-process the
+# specifiers here to "fix" them.
+
+SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
+
+set -euo pipefail
+
+pushd $SCRIPT_DIR/../src/openapi-client
+
+find ./ -type f -exec sed -i "/import\|export/ s/\(.* '\.\/[^']*\)/\0.js/g" {} +
+
+popd
+
+
+
diff --git a/typescript/packages/usuba-sw/scripts/update-openapi-spec.sh b/typescript/packages/usuba-api/scripts/update-openapi-spec.sh
similarity index 100%
rename from typescript/packages/usuba-sw/scripts/update-openapi-spec.sh
rename to typescript/packages/usuba-api/scripts/update-openapi-spec.sh
diff --git a/typescript/packages/usuba-api/src/index.ts b/typescript/packages/usuba-api/src/index.ts
new file mode 100644
index 000000000..a2eea3b30
--- /dev/null
+++ b/typescript/packages/usuba-api/src/index.ts
@@ -0,0 +1 @@
+export * from './openapi-client/index.js';
diff --git a/typescript/packages/usuba-api/tsconfig.json b/typescript/packages/usuba-api/tsconfig.json
new file mode 100644
index 000000000..19199d7df
--- /dev/null
+++ b/typescript/packages/usuba-api/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "lib": ["ES2022", "WebWorker"],
+ "outDir": "./lib",
+ "rootDir": "./src",
+ },
+ "include": [
+ "src/**/*"
+ ]
+}
diff --git a/typescript/packages/usuba-rt/package.json b/typescript/packages/usuba-rt/package.json
new file mode 100644
index 000000000..2fa2c694e
--- /dev/null
+++ b/typescript/packages/usuba-rt/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "@commontools/usuba-rt",
+ "author": "The Common Authors",
+ "version": "0.0.1",
+ "description": "A Runtime for managing the invocation of Usuba-produced Modules",
+ "license": "UNLICENSED",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "wireit",
+ "clean": "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",
+ "exports": "./lib/index.js",
+ "files": [
+ "./lib/*.js"
+ ],
+ "dependencies": {
+ "@commontools/usuba-api": "^0.0.1"
+ },
+ "devDependencies": {
+ "tslib": "^2.6.2",
+ "typescript": "^5.2.2",
+ "wireit": "^0.14.4"
+ },
+ "wireit": {
+ "build": {
+ "dependencies": [
+ "../usuba-api:build"
+ ],
+ "files": [
+ "./src/**/*"
+ ],
+ "output": [
+ "./lib/**/*"
+ ],
+ "command": "tsc --build -f"
+ },
+ "clean": {
+ "command": "rm -rf ./lib ./.wireit"
+ }
+ }
+}
\ No newline at end of file
diff --git a/typescript/packages/usuba-rt/src/index.ts b/typescript/packages/usuba-rt/src/index.ts
new file mode 100644
index 000000000..537a635fd
--- /dev/null
+++ b/typescript/packages/usuba-rt/src/index.ts
@@ -0,0 +1,219 @@
+import * as apiClient from '@commontools/usuba-api';
+
+export type SourceCode = string | Uint8Array;
+export type PendingSourceCode = SourceCode | Promise;
+
+export type ContentType = 'text/javascript' | 'text/x-python';
+
+export type ContentTypeFileExtensions = {
+ [C in ContentType]: string;
+};
+
+export interface ModuleDefinition {
+ contentType: ContentType;
+ wit: PendingSourceCode;
+ sourceCode: PendingSourceCode;
+}
+
+export type Import = {
+ [index: string]: any;
+};
+
+export type ImportMap = {
+ [index: string]: Import;
+};
+
+export type Importable = string | Import | Promise;
+
+export type ImportableMap = {
+ [index: string]: Importable;
+};
+
+const FILE_EXTENSIONS: ContentTypeFileExtensions = {
+ 'text/javascript': 'js',
+ 'text/x-python': 'py',
+};
+
+const serviceWorkerActivates = (async () => {
+ if (typeof navigator.serviceWorker == 'undefined') {
+ throw new Error(
+ 'Service Worker is not supported in this browser; Usuba will not work here.'
+ );
+ }
+
+ try {
+ const registration = await navigator.serviceWorker.register(
+ '/usuba-sw.js',
+ {
+ type: 'module',
+ scope: '/',
+ }
+ );
+
+ const hasPending =
+ registration.active && (registration.installing || registration.waiting);
+
+ let installationFinishes = !hasPending
+ ? Promise.resolve()
+ : new Promise((resolve) => {
+ if (registration.waiting) {
+ return self.location.reload();
+ }
+
+ registration.installing?.addEventListener(
+ 'statechange',
+ async (_) => {
+ if (registration.waiting) {
+ self.location.reload();
+ } else {
+ resolve(undefined);
+ }
+ }
+ );
+ });
+
+ await installationFinishes;
+
+ console.log('Usuba Service Worker is active!');
+ } catch (error) {
+ console.error(`Registration failed with ${error}`);
+ }
+})();
+
+/**
+ * A Runtime embodies:
+ *
+ * - A Standard Library interface, defined as WIT
+ * - A REST client for producing On-demand Isolated Modules
+ *
+ * Its main interface enables the user to Prepare a Module for future
+ * instantiation.
+ *
+ * When constructing a Runtime, the provided library may be a mix of actual WIT
+ * definitions or promises that resolve to WIT definitions.
+ */
+export class Runtime {
+ #serviceWorkerActivates: Promise = serviceWorkerActivates;
+ #library: Promise;
+ #usubaHost: URL;
+
+ constructor(
+ library: PendingSourceCode[],
+ usubaHost: URL = new URL(window.location.origin)
+ ) {
+ this.#library = Promise.all(library).then((library) =>
+ library.map(
+ (item, index) =>
+ new File(
+ [new Blob([item], { type: 'text/plain' })],
+ `library-${index}.wit`
+ )
+ )
+ );
+ this.#usubaHost = usubaHost;
+ }
+
+ /**
+ * Prepares a module for instantiation by converting the provided source
+ * definition to a Wasm Component, and then subsequently polyfilling it for
+ * browser-based Core Wasm. The resulting prepared module can be instantiated
+ * by providing it with a working implementation of the library associated
+ * with the runtime that defined it.
+ *
+ * @param definition The essential details of the module being defined
+ * @returns A promise that resolves to the prepared
+ */
+ async defineModule(
+ definition: ModuleDefinition
+ ): Promise> {
+ const [library, wit, sourceCode, _] = await Promise.all([
+ this.#library,
+ definition.wit,
+ definition.sourceCode,
+ this.#serviceWorkerActivates,
+ ]);
+
+ apiClient.OpenAPI.BASE = this.#usubaHost.origin;
+ const { id } = await apiClient.buildModule({
+ formData: {
+ library,
+ module: [
+ new File([new Blob([wit], { type: 'text/plain' })], 'module.wit'),
+ new File(
+ [new Blob([sourceCode], { type: definition.contentType })],
+ `module.${FILE_EXTENSIONS[definition.contentType]}`
+ ),
+ ],
+ },
+ });
+
+ const { instantiate } = await import(
+ /* @vite-ignore */ `${
+ this.#usubaHost.origin
+ }/module/transpiled/runtime/${id}.js`
+ );
+
+ return new PreparedModule(
+ instantiate as (imports: ImportMap) => Promise
+ );
+ }
+}
+
+/**
+ * A PreparedModule embodies:
+ *
+ * - Polyfill artifacts consisting of Wasm Modules and JavaScript bindings
+ * - Association to the Runtime that created it through its Standard Library
+ *
+ * Its main interface enables the user to Instantiate a Module with a
+ * just-in-time Standard Library. The product of successful instantiation is
+ * always an implementation of the interface defined by the Module's WIT.
+ */
+export class PreparedModule {
+ #instantiate: (imports: ImportMap) => Promise;
+
+ constructor(instantiate: any) {
+ this.#instantiate = instantiate;
+ }
+
+ /**
+ * Instantiates a prepared module, yielding a promise that resolves to the
+ * module's API (as defined in its WIT).
+ *
+ * In order to instantiate the prepared module, you must provide it with a
+ * mapping of module specifiers to concrete implementations. These will be
+ * used to populate the "library" associated with the prepared module's
+ * runtime. Only the imports that are made use of by the code in the prepared
+ * module need to be specified.
+ *
+ * This method uses different techniques to resolve a concrete library
+ * implemenetation depending on the value type in the provided mapping:
+ *
+ * - string: the value will be treated as a module specifier, and will be
+ * resolved using a dynamic import
+ * - promise: the value will be the resolved value of the promise
+ * - all other types are treated as a candidate implementation of the library
+ *
+ * @param importables A mapping of library imports to their eventual
+ * implementations
+ * @returns A promise that resolves to the instantiated module's API
+ */
+ async instantiate(importables: ImportableMap): Promise {
+ const importedEntries = (await Promise.all(
+ Object.entries(importables).map(async ([key, importable]) => {
+ if (typeof importable == 'string') {
+ importable = import(/* @vite-ignore */ importable) as Promise;
+ }
+
+ return [key, await importable];
+ })
+ )) as [string, Import][];
+
+ const imports = importedEntries.reduce((map, [key, imported]) => {
+ map[key] = imported;
+ return map;
+ }, {} as ImportMap);
+
+ return await this.#instantiate(imports);
+ }
+}
diff --git a/typescript/packages/usuba-rt/tsconfig.json b/typescript/packages/usuba-rt/tsconfig.json
new file mode 100644
index 000000000..d40c067b9
--- /dev/null
+++ b/typescript/packages/usuba-rt/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "lib": ["es2022", "DOM", "DOM.Iterable"],
+ "outDir": "./lib",
+ "rootDir": "./src",
+ },
+ "include": [
+ "src/**/*",
+ ]
+}
diff --git a/typescript/packages/usuba-sw/openapi.json b/typescript/packages/usuba-sw/openapi.json
index 58b8bbaa0..5c840421b 100644
--- a/typescript/packages/usuba-sw/openapi.json
+++ b/typescript/packages/usuba-sw/openapi.json
@@ -105,11 +105,20 @@
"schemas": {
"BuildModuleRequest": {
"type": "object",
+ "description": "A `multipart/form-data` payload that consists of module WIT + source code as\nwell as additional (optional) library WIT files",
"required": [
- "files"
+ "module",
+ "library"
],
"properties": {
- "files": {
+ "library": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "binary"
+ }
+ },
+ "module": {
"type": "array",
"items": {
"type": "string",
diff --git a/typescript/packages/usuba-sw/package.json b/typescript/packages/usuba-sw/package.json
index cb3b2ce63..89d21dcd8 100644
--- a/typescript/packages/usuba-sw/package.json
+++ b/typescript/packages/usuba-sw/package.json
@@ -8,7 +8,7 @@
"type": "module",
"scripts": {
"build": "wireit",
- "update-openapi-spec": "wireit"
+ "clean": "wireit"
},
"repository": {
"type": "git",
@@ -21,7 +21,9 @@
"files": [
"./dist/usuba-sw.js"
],
- "dependencies": {},
+ "dependencies": {
+ "@commontools/usuba-api": "^0.0.1"
+ },
"devDependencies": {
"@bytecodealliance/preview2-shim": "^0.16.2",
"@hey-api/openapi-ts": "^0.46.0",
@@ -31,15 +33,6 @@
"wireit": "^0.14.4"
},
"wireit": {
- "update-openapi-spec": {
- "command": "./scripts/update-openapi-spec.sh"
- },
- "build:openapi-client": {
- "files": [
- "./openapi.json"
- ],
- "command": "npx @hey-api/openapi-ts -i ./openapi.json -o ./src/openapi-client"
- },
"build:wasm": {
"command": "../../../rust/usuba-compat/build-wasm-component.sh",
"files": [
@@ -51,13 +44,20 @@
},
"build": {
"dependencies": [
- "build:wasm",
- "build:openapi-client"
+ "../usuba-api:build",
+ "build:wasm"
],
"files": [
"./src/**/*"
],
+ "output": [
+ "./lib/**/*",
+ "./dist/*"
+ ],
"command": "tsc --build -f && cp -r ./src/usuba_compat ./lib/usuba_compat && vite build"
+ },
+ "clean": {
+ "command": "rm -rf ./lib ./dist ./.wireit"
}
}
}
\ No newline at end of file
diff --git a/typescript/packages/usuba-sw/src/index.ts b/typescript/packages/usuba-sw/src/index.ts
index 50b6bbf29..d16f3c849 100644
--- a/typescript/packages/usuba-sw/src/index.ts
+++ b/typescript/packages/usuba-sw/src/index.ts
@@ -1,123 +1,334 @@
-import * as apiClient from './openapi-client/services.gen';
-import { polyfill } from './usuba_compat/usuba_compat.component.js';
+import * as apiClient from '@commontools/usuba-api';
+import { polyfill, hash } from './usuba_compat/usuba_compat.component.js';
+
+const SERVICE_WORKER_VERSION = '0.0.1-alpha.6';
self.addEventListener('install', (_event) => {
- console.log('Usuba Service Worker installed');
+ console.log(
+ `Usuba Service Worker installed (version ${SERVICE_WORKER_VERSION})`
+ );
});
-self.addEventListener('fetch', async (event: FetchEvent) => {
- if (event.request.method !== 'GET') {
- return;
+const WASI_SHIM_MAP = {
+ 'wasi:cli/*': '/wasi-shim/cli.js#*',
+ 'wasi:clocks/*': '/wasi-shim/clocks.js#*',
+ 'wasi:filesystem/*': '/wasi-shim/filesystem.js#*',
+ 'wasi:http/*': '/wasi-shim/http.js#*',
+ 'wasi:io/*': '/wasi-shim/io.js#*',
+ 'wasi:random/*': '/wasi-shim/random.js#*',
+ 'wasi:sockets/*': '/wasi-shim/sockets.js#*',
+};
+
+const ON_DEMAND_TRANSPILED_MODULES_CACHE_NAME =
+ 'v1/modules/transpiled/on-demand';
+const RUNTIME_TRANSPILED_MODULES_CACHE_NAME = 'v1/modules/transpiled/runtime';
+
+const ON_DEMAND_TRANSPILED_MODULE_DIRNAME = '/module/transpiled/on-demand';
+const ON_DEMAND_BUILD_DIRNAME = '/module/on-demand';
+
+const RUNTIME_TRANSPILED_MODULE_DIRNAME = '/module/transpiled/runtime';
+const RUNTIME_BUILD_DIRNAME = '/api/v0/module';
+
+/**
+ * For a given request, if an item in the specified cache matches a specified
+ * URL (which may be different from the request URL), respond from the cache.
+ * Otherwise, forward the request.
+ */
+const respondFromCache = (event: FetchEvent, url: URL, cacheName: string) => {
+ event.respondWith(
+ (async () => {
+ const cache = await caches.open(cacheName);
+ const cacheResponse = await cache.match(url);
+
+ if (cacheResponse) {
+ return cacheResponse;
+ } else {
+ return fetch(event.request);
+ }
+ })()
+ );
+};
+
+/**
+ * Perform the steps to build a Module, first by invoking the Build Server
+ * and then by transpiling the resulting Wasm Component. Returns the artifacts
+ * of a successful transpilation.
+ */
+const buildModule = async (
+ slug: string,
+ module: File[],
+ library: File[],
+ instantiation: 'automatic' | 'manual' = 'automatic'
+): Promise> => {
+ const moduleId = (
+ await apiClient.buildModule({
+ formData: {
+ library,
+ module,
+ },
+ })
+ ).id;
+
+ const moduleBytes = new Uint8Array(
+ await (
+ await apiClient.retrieveModule({
+ id: moduleId,
+ })
+ ).arrayBuffer()
+ );
+
+ return polyfill(moduleBytes, {
+ name: slug,
+ mappings: Object.entries(WASI_SHIM_MAP),
+ instantiation,
+ });
+};
+
+/**
+ * Cache build artifacts, and generate / cache an entrypoint "wrapper"
+ * that re-exports the transpiled Wasm Component.
+ */
+const shrinkWrap = async (
+ entrypointUrl: URL,
+ wrapperModule: string,
+ files: [string, Uint8Array][],
+ cacheName: string,
+ dirName: string
+): Promise => {
+ const cache = await caches.open(cacheName);
+
+ for (const [filename, bytes] of files) {
+ console.log('Caching artifact:', filename);
+
+ const blob = new Blob([bytes], {
+ type: filename.endsWith('.wasm') ? 'application/wasm' : 'text/javascript',
+ });
+
+ const nextUrl = new URL(`${dirName}/${filename}`, entrypointUrl.origin);
+ await cache.put(nextUrl, new Response(blob));
}
- const requestUrl = new URL(event.request.url);
+ const blob = new Blob([wrapperModule], { type: 'text/javascript' });
+ const response = new Response(blob);
+
+ await cache.put(entrypointUrl, response.clone());
+
+ return response;
+};
+
+/**
+ * The on-demand build flow is distinguished in two ways:
+ *
+ * 1. The flow starts with a GET request and yields an importable module
+ * 2. Module instantiation is automatic (its imports aren't configurable)
+ */
+const buildOnDemandModule = (event: FetchEvent, url: URL) => {
+ event.respondWith(
+ (async () => {
+ console.log('On-demand module generation detected...');
+ url.pathname.split('/').slice(2);
+
+ const [ext, witBase64, sourceCodeBase64] = url.pathname
+ .split('/')
+ .slice(3);
+
+ console.log('Attempting to parse on-demand path fragment...');
+
+ if (ext && witBase64 && sourceCodeBase64) {
+ const encoder = new TextEncoder();
+ const polyfilledModuleId = hash(
+ encoder.encode(`${witBase64}.${sourceCodeBase64}`)
+ );
+ const cache = await caches.open(
+ ON_DEMAND_TRANSPILED_MODULES_CACHE_NAME
+ );
+ const moduleShortId = polyfilledModuleId.slice(0, 6);
+ const moduleSlug = `module-${moduleShortId}`;
- if (requestUrl.pathname.startsWith('/module/transpiled')) {
- console.log('Pulling generated artifact from cache...');
- event.respondWith(
- (async () => {
- const cache = await caches.open('v0/modules/transpiled');
- const cacheResponse = await cache.match(requestUrl);
- if (cacheResponse) {
- return cacheResponse;
- } else {
- return fetch(event.request);
+ const entrypointModule = `${ON_DEMAND_TRANSPILED_MODULE_DIRNAME}/${moduleSlug}-wrapper.js`;
+ const entrypointUrl = new URL(entrypointModule, url.origin);
+
+ const cacheItem = await cache.match(entrypointUrl);
+
+ if (typeof cacheItem != 'undefined') {
+ console.log('Polyfilled on-demand module found in cache!');
+ return cacheItem;
}
- })()
- );
- } else if (requestUrl.pathname.startsWith('/module/on-demand')) {
- console.log('On-demand module generation detected...');
- requestUrl.pathname.split('/').slice(2);
-
- const [ext, witBase64, sourceCodeBase64] = requestUrl.pathname
- .split('/')
- .slice(3);
-
- console.log('Attempting to parse on-demand path fragment...');
-
- if (ext && witBase64 && sourceCodeBase64) {
- const wit = atob(witBase64);
- const sourceCode = atob(sourceCodeBase64);
-
- console.log('File extension:', ext);
- console.log('WIT:\n', wit);
- console.log('Source Code:\n', sourceCode);
-
- const witFile = new File([new Blob([wit])], 'module.wit');
- const sourceCodeFile = new File(
- [new Blob([sourceCode])],
- `module.${ext}`
- );
- event.respondWith(
- (async () => {
- const moduleId = (
- await apiClient.buildModule({
- formData: {
- files: [witFile, sourceCodeFile],
- },
- })
- ).id;
-
- const moduleBytes = new Uint8Array(
- await (
- await apiClient.retrieveModule({
- id: moduleId,
- })
- ).arrayBuffer()
- );
- const cache = await caches.open('v0/modules/transpiled');
- const fileSlug = `module-${moduleId.slice(0, 6)}`;
-
- const entrypointModule = `/module/transpiled/${fileSlug}.js`;
- const maybeHotUrl = new URL(entrypointModule, requestUrl.origin);
-
- if (!(await cache.match(maybeHotUrl))) {
- const {
- files,
- imports: _imports,
- exports: _exports,
- } = polyfill(moduleBytes, {
- name: fileSlug,
- mappings: Object.entries({
- 'wasi:cli/*': '/wasi-shim/cli.js#*',
- 'wasi:clocks/*': '/wasi-shim/clocks.js#*',
- 'wasi:filesystem/*': '/wasi-shim/filesystem.js#*',
- 'wasi:http/*': '/wasi-shim/http.js#*',
- 'wasi:io/*': '/wasi-shim/io.js#*',
- 'wasi:random/*': '/wasi-shim/random.js#*',
- 'wasi:sockets/*': '/wasi-shim/sockets.js#*',
- }),
- });
-
- for (const [filename, bytes] of files) {
- console.log('Caching artifact:', filename);
- const blob = new Blob([bytes], {
- type: filename.endsWith('.wasm')
- ? 'application/wasm'
- : 'text/javascript',
- });
- const url = new URL(
- `/module/transpiled/${filename}`,
- requestUrl.origin
- );
-
- await cache.put(url, new Response(blob));
- }
- }
-
- const wrapperModule = `export * from '/module/transpiled/${fileSlug}.js'`;
- const blob = new Blob([wrapperModule], { type: 'text/javascript' });
-
- return new Response(blob);
- })()
+ console.log("Nothing found in cache; we'll do it live!");
+
+ const wit = atob(witBase64);
+ const sourceCode = atob(sourceCodeBase64);
+
+ console.log('File extension:', ext);
+ console.log('WIT:\n', wit);
+ console.log('Source Code:\n', sourceCode);
+
+ const witFile = new File([new Blob([wit])], 'module.wit');
+ const sourceCodeFile = new File(
+ [new Blob([sourceCode])],
+ `module.${ext}`
+ );
+
+ const {
+ files,
+ imports: _imports,
+ exports: _exports,
+ } = await buildModule(
+ moduleSlug,
+ [witFile, sourceCodeFile],
+ [],
+ 'automatic'
+ );
+
+ const wrapperModule = `export * from '${ON_DEMAND_TRANSPILED_MODULE_DIRNAME}/${moduleSlug}.js'`;
+
+ return await shrinkWrap(
+ entrypointUrl,
+ wrapperModule,
+ files,
+ ON_DEMAND_TRANSPILED_MODULES_CACHE_NAME,
+ ON_DEMAND_TRANSPILED_MODULE_DIRNAME
+ );
+ } else {
+ return new Response(new Blob([], { type: 'text/html' }), {
+ status: 404,
+ });
+ }
+ })()
+ );
+};
+
+/**
+ * A Runtime Module is built when the Service Worker intercepts an API request
+ * to the Build Server. The Wasm Component (produced by the Build Server) is
+ * transpiled and cached locally, and a derived Module ID is given to the caller
+ * (not the original Wasm Component ID). This allows the caller to provide an
+ * arbitrary number of input files with an initial POST, and then instantiate
+ * the Runtime Module "just in time" using a secondary import.
+ *
+ * Instantiation of a Runtime Module is manual, which means that it allows for
+ * imports to be configured at instantiation time. But, it also means that a
+ * Runtime Module cannot be imported transparently the way an On-demand Module
+ * can. Instead, the result of importing a Runtime Module is an `instantiate`
+ * function that yields the actual module.
+ */
+const buildRuntimeModule = (event: FetchEvent, url: URL) => {
+ event.respondWith(
+ (async () => {
+ console.log('Preparing to build Runtime Module...');
+ const formData = await event.request.formData();
+ const moduleFiles = formData.getAll('module') as File[];
+ const libraryFiles = formData.getAll('library') as File[];
+
+ const allFiles = moduleFiles.concat(libraryFiles);
+
+ const runtimeModuleId = hash(
+ new Uint8Array(
+ await new Blob(
+ await Promise.all(allFiles.map((file) => file.arrayBuffer()))
+ ).arrayBuffer()
+ )
);
+
+ const cache = await caches.open(RUNTIME_TRANSPILED_MODULES_CACHE_NAME);
+ const moduleShortId = runtimeModuleId.slice(0, 6);
+ const moduleSlug = `module-${moduleShortId}`;
+
+ const buildResultPath = `${RUNTIME_TRANSPILED_MODULE_DIRNAME}/result-${moduleSlug}.json`;
+ const buildResultUrl = new URL(buildResultPath, url.origin);
+
+ const cacheItem = await cache.match(buildResultUrl);
+
+ if (typeof cacheItem != 'undefined') {
+ console.log('Polyfilled runtime module build result found in cache!');
+ return cacheItem;
+ }
+
+ const {
+ files,
+ imports: _imports,
+ exports: _exports,
+ } = await buildModule(moduleSlug, moduleFiles, libraryFiles, 'manual');
+
+ const wrapperModule = `import {instantiate as innerInstantiate} from '${RUNTIME_TRANSPILED_MODULE_DIRNAME}/${moduleSlug}.js';
+import {shim as wasiShimImportPromises} from '/wasi.js';
+
+const wasiShimImports = Promise.all(
+ Object.entries(wasiShimImportPromises)
+ .map(([specifier, importPromise]) =>
+ importPromise.then((importResult) => [specifier, importResult])
+ )
+);
+
+export const instantiate = async (imports) => {
+ const resolvedWasiShimImports = await wasiShimImports;
+
+ for (const [name, shimImport] of resolvedWasiShimImports) {
+ if (typeof imports[name] == 'undefined') {
+ imports[name] = shimImport;
}
}
-});
-/*
-
+ const getCoreModule = async (name) => fetch('${RUNTIME_TRANSPILED_MODULE_DIRNAME}/' + name).then(WebAssembly.compileStreaming);
+ console.log('Instantiating module with these resolved imports:', imports);
+
+ return innerInstantiate(getCoreModule, imports);
+};`;
+
+ await shrinkWrap(
+ new URL(
+ `${RUNTIME_TRANSPILED_MODULE_DIRNAME}/${runtimeModuleId}.js`,
+ url.origin
+ ),
+ wrapperModule,
+ files,
+ RUNTIME_TRANSPILED_MODULES_CACHE_NAME,
+ RUNTIME_TRANSPILED_MODULE_DIRNAME
+ );
+
+ const response = new Response(
+ new Blob([JSON.stringify({ id: runtimeModuleId })], {
+ type: 'application/json',
+ })
+ );
+
+ await cache.put(buildResultUrl, response.clone());
-
-*/
+ return response;
+ })()
+ );
+};
+
+self.addEventListener('fetch', async (event: FetchEvent) => {
+ const requestUrl = new URL(event.request.url);
+
+ switch (event.request.method) {
+ case 'GET':
+ if (requestUrl.pathname.startsWith(ON_DEMAND_TRANSPILED_MODULE_DIRNAME)) {
+ respondFromCache(
+ event,
+ requestUrl,
+ ON_DEMAND_TRANSPILED_MODULES_CACHE_NAME
+ );
+ } else if (
+ requestUrl.pathname.startsWith(RUNTIME_TRANSPILED_MODULE_DIRNAME)
+ ) {
+ respondFromCache(
+ event,
+ requestUrl,
+ RUNTIME_TRANSPILED_MODULES_CACHE_NAME
+ );
+ } else if (requestUrl.pathname.startsWith(ON_DEMAND_BUILD_DIRNAME)) {
+ buildOnDemandModule(event, requestUrl);
+ }
+ break;
+ case 'POST':
+ if (requestUrl.pathname.startsWith(RUNTIME_BUILD_DIRNAME)) {
+ buildRuntimeModule(event, requestUrl);
+ }
+ break;
+ default:
+ break;
+ }
+});
diff --git a/typescript/packages/usuba-sw/tsconfig.json b/typescript/packages/usuba-sw/tsconfig.json
index e0ddf35f7..de354019b 100644
--- a/typescript/packages/usuba-sw/tsconfig.json
+++ b/typescript/packages/usuba-sw/tsconfig.json
@@ -1,29 +1,8 @@
{
+ "extends": "../../tsconfig.base.json",
"compilerOptions": {
- "composite": true,
- "target": "es2021",
- "module": "es6",
- "lib": ["es2021"],
- "declaration": true,
- "declarationMap": true,
- "sourceMap": true,
- "inlineSources": true,
"outDir": "./lib",
"rootDir": "./src",
- "strict": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "noImplicitReturns": true,
- "noFallthroughCasesInSwitch": true,
- "noImplicitAny": true,
- "noImplicitThis": true,
- "moduleResolution": "node",
- "allowSyntheticDefaultImports": true,
- "experimentalDecorators": true,
- "importHelpers": true,
- "stripInternal": true,
- "noImplicitOverride": true,
- "types": []
},
"include": [
"src/**/*",
diff --git a/typescript/packages/usuba-sw/tsconfig.tsbuildinfo b/typescript/packages/usuba-sw/tsconfig.tsbuildinfo
deleted file mode 100644
index 164f511dd..000000000
--- a/typescript/packages/usuba-sw/tsconfig.tsbuildinfo
+++ /dev/null
@@ -1 +0,0 @@
-{"program":{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","./src/openapi-client/core/CancelablePromise.ts","./src/openapi-client/core/ApiRequestOptions.ts","./src/openapi-client/core/OpenAPI.ts","./src/openapi-client/core/ApiResult.ts","./src/openapi-client/core/ApiError.ts","./src/openapi-client/core/request.ts","./src/openapi-client/types.gen.ts","./src/openapi-client/services.gen.ts","./src/usuba_compat/interfaces/wasi-cli-environment.d.ts","./src/usuba_compat/interfaces/wasi-cli-exit.d.ts","./src/usuba_compat/interfaces/wasi-io-error.d.ts","./src/usuba_compat/interfaces/wasi-io-streams.d.ts","./src/usuba_compat/interfaces/wasi-cli-stderr.d.ts","./src/usuba_compat/interfaces/wasi-cli-stdin.d.ts","./src/usuba_compat/interfaces/wasi-cli-stdout.d.ts","./src/usuba_compat/interfaces/wasi-clocks-wall-clock.d.ts","./src/usuba_compat/interfaces/wasi-filesystem-types.d.ts","./src/usuba_compat/interfaces/wasi-filesystem-preopens.d.ts","./src/usuba_compat/interfaces/wasi-random-random.d.ts","./src/usuba_compat/usuba_compat.component.d.ts","./src/index.ts","./src/openapi-client/schemas.gen.ts","./src/openapi-client/index.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-environment.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-exit.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-run.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-io-error.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-io-poll.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-io-streams.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-stderr.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-stdin.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-stdout.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-terminal-input.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-terminal-output.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-terminal-stderr.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-terminal-stdin.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-cli-terminal-stdout.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/cli.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-clocks-monotonic-clock.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-clocks-wall-clock.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/clocks.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-filesystem-types.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-filesystem-preopens.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/filesystem.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-http-types.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-http-incoming-handler.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-http-outgoing-handler.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/http.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/io.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-random-insecure-seed.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-random-insecure.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-random-random.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/random.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-sockets-network.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-sockets-instance-network.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-sockets-ip-name-lookup.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-sockets-tcp.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-sockets-tcp-create-socket.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-sockets-udp.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/interfaces/wasi-sockets-udp-create-socket.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/sockets.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/index.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/wasi-cli-command.d.ts","../../node_modules/@bytecodealliance/preview2-shim/types/wasi-http-proxy.d.ts","../../node_modules/@types/serviceworker/iterable.d.ts","../../node_modules/@types/serviceworker/index.d.ts"],"fileInfos":[{"version":"824cb491a40f7e8fdeb56f1df5edf91b23f3e3ee6b4cde84d4a99be32338faee","affectsGlobalScope":true},"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","9a68c0c07ae2fa71b44384a839b7b8d81662a236d4b9ac30916718f7510b1b2d","5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569",{"version":"138fb588d26538783b78d1e3b2c2cc12d55840b97bf5e08bca7f7a174fbe2f17","affectsGlobalScope":true},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true},{"version":"4443e68b35f3332f753eacc66a04ac1d2053b8b035a0e0ac1d455392b5e243b3","affectsGlobalScope":true},{"version":"bc47685641087c015972a3f072480889f0d6c65515f12bd85222f49a98952ed7","affectsGlobalScope":true},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true},{"version":"93495ff27b8746f55d19fcbcdbaccc99fd95f19d057aed1bd2c0cafe1335fbf0","affectsGlobalScope":true},{"version":"6fc23bb8c3965964be8c597310a2878b53a0306edb71d4b5a4dfe760186bcc01","affectsGlobalScope":true},{"version":"ea011c76963fb15ef1cdd7ce6a6808b46322c527de2077b6cfdf23ae6f5f9ec7","affectsGlobalScope":true},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true},{"version":"bb42a7797d996412ecdc5b2787720de477103a0b2e53058569069a0e2bae6c7e","affectsGlobalScope":true},{"version":"4738f2420687fd85629c9efb470793bb753709c2379e5f85bc1815d875ceadcd","affectsGlobalScope":true},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true},{"version":"9fc46429fbe091ac5ad2608c657201eb68b6f1b8341bd6d670047d32ed0a88fa","affectsGlobalScope":true},{"version":"61c37c1de663cf4171e1192466e52c7a382afa58da01b1dc75058f032ddf0839","affectsGlobalScope":true},{"version":"b541a838a13f9234aba650a825393ffc2292dc0fc87681a5d81ef0c96d281e7a","affectsGlobalScope":true},{"version":"b20fe0eca9a4e405f1a5ae24a2b3290b37cf7f21eba6cbe4fc3fab979237d4f3","affectsGlobalScope":true},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true},{"version":"49ed889be54031e1044af0ad2c603d627b8bda8b50c1a68435fe85583901d072","affectsGlobalScope":true},{"version":"e93d098658ce4f0c8a0779e6cab91d0259efb88a318137f686ad76f8410ca270","affectsGlobalScope":true},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true},{"version":"bf14a426dbbf1022d11bd08d6b8e709a2e9d246f0c6c1032f3b2edb9a902adbe","affectsGlobalScope":true},{"version":"5e07ed3809d48205d5b985642a59f2eba47c402374a7cf8006b686f79efadcbd","affectsGlobalScope":true},{"version":"2b72d528b2e2fe3c57889ca7baef5e13a56c957b946906d03767c642f386bbc3","affectsGlobalScope":true},{"version":"8073890e29d2f46fdbc19b8d6d2eb9ea58db9a2052f8640af20baff9afbc8640","affectsGlobalScope":true},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true},{"version":"51e547984877a62227042850456de71a5c45e7fe86b7c975c6e68896c86fa23b","affectsGlobalScope":true},{"version":"956d27abdea9652e8368ce029bb1e0b9174e9678a273529f426df4b3d90abd60","affectsGlobalScope":true},{"version":"33358442698bb565130f52ba79bfd3d4d484ac85fe33f3cb1759c54d18201393","affectsGlobalScope":true},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true},{"version":"663237e06287606be7ccdb892ddc9562352aec15dedca983ac84004c2b1b17cc","signature":"11a746b4d1023300a23da9afb502364b8a67874b00f34fd92c3adcf605e49368"},{"version":"f49f644231f39b74684e103ae64a56952d8eb263b79bf35574d8379e0a01056e","signature":"133b004d5fec7847b2043006864672606223edffb06fe0726b5506da919500e5"},{"version":"64d75e977b227615ff85a8fc46bc56148eeb5143cb86c9d4bc196fabc89d4ea9","signature":"c209b0f634e8337bb9ef368d842d38d3a95f32cbd8b0df3b1c5ffa386e2fb067"},{"version":"8b8a47fd8c3b647c999ac6f83c85e7f0b851a8954c148a787d9e8e90f3b7da4e","signature":"1499eebe9457d103b9b5782b243797305ca7f26e198d384c2e0b2a25d6f10bde"},{"version":"95f506c7f6b38262bd5932f87820faab73121e08bd9306ce440b732a9443fe95","signature":"358537bc98289ec8e0a883558469c877a4fbe38a15d023f7e0456e4a4f72bcd8"},{"version":"eabebdebcb2173d4679f69c60d9dd32d4fdc5beefeea62fdce60e91d949e08f4","signature":"7d67dcebda39234142a94b0f3949b1410ffcae09318dfe2f98af3c0d68babd75"},{"version":"fa7afa288e7f17ed0f9618b510333a3b8449cba201af4c1132fff13cedd22c2f","signature":"a4c847ed607f44f7b2b1c1e7fd254b572faa1c54f82b4ca2d39a6a40b14e4b67"},{"version":"98c47f37dba0f3c9b0807003aa56195eeed9dc70bee53b2d0034ff2841667992","signature":"bf5be703ddfcada43840ed728f03d8fd1529fdce43b2ca35eaaabd7bb17cf68f"},"5c972c15e17460c7187ca686ad4f849ec67fd80973dd081040d101cbb6289c0f","6d978b7e6fe437e74fd706a46aa068e95ce527707fc1bcd0581b42ad2d6cd857","051889e07ae7cce2fda01c0205b2094e4b6af8fc15d94c1fbf74e243791367e9","4771dc75aef3e1ca2c94755fafa3a2fabe901e2c228f44863396304225574e12","40b503e330de157566a04cf9c3d2fa25884202627182383aa9a93241f9aa181e","afa98d3b6a0444ae8c3917468410fe970fd89b591b74fc05613cde891923448d","f7b9b849771d5ad94c0b7942ad7ad9a8b9be8c06bb9ca9b87808be9b035e9e11","389dc524ad7c8b880df9287266597830f9fa6eff0279cac2e41cc626508e5344","bfd13eb3b7b5d7be0ebf666ab855eed9f6f78faef9efea64d41f966807dbf53b","7f071c1d1eb9b7cb04bcf38f765ddaebcbba2baf00f4958913e6c888529b2144","db671aadda72ca3d173bf3540d52366e0b7727855a83c64526eacdcfa751b372","3ade56ac91b009a34bdd91d2de3dfee48da335de8a7fd9192fdb9ddd45df95f0",{"version":"114c5a0b52752c12622b5733a176dbf61f27cb6bc4c70a7b031751bdae7ea1bc","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"cf3464cf28790cf6ff84a62c082940148bd7a05967c5a9a216f6b853a669c8a7","signature":"b01c7ed36a99de419dcb74dffb8ef99b2daf87e64522d9a9198be94fb240e3c7"},{"version":"7b2931f49e92fdcd2af4f577707392ad2c3d3a71a8ee78c07418d83b7540fcdf","signature":"139558747accfba69018e47cc01ffa611a8afdfc75fcc218276ec7aad96f246b"},"8a95678ae9f5199675902f24f3fd2a2b1759d1246198f53d0076890c8f3a89ca","648cdcd5baccca30b3c217976c52463269071a3a0a8f6784a95e7818f7b8abad","c033bb2c56ec100557bb616c98f8ad4648ca263062ad9f9f8a1e8bc71694052c","7ae0338b32bd72df596a5f49daa37c4ba5046d44ca77dd294325a8a0a612b744","8d52b8d32199c9f1e9bec474d5fff4a80dbc2079a277f68d5548e6b2649590d8","5ee4bd3be80e194388bf521245bbcf8d44d5c148d18b6bb262d3617b89e91421","40b503e330de157566a04cf9c3d2fa25884202627182383aa9a93241f9aa181e","afa98d3b6a0444ae8c3917468410fe970fd89b591b74fc05613cde891923448d","f7b9b849771d5ad94c0b7942ad7ad9a8b9be8c06bb9ca9b87808be9b035e9e11","9179a85ab76d3118975c391f747d408172ff0544f8b46763639a74883f437bfd","e06a866dcb1161b68602c62bc03c3f1cedede1576003e3697babd853bd3edefc","3f464b0aa7697aae1d05cd4cdc05e84e5befed0a4613279bbfaabca912d9f814","3a8c7f5622f3618a8c5b73537207cc4bbff8ba4ce5acdaaf6a67f13bf5e0badd","9186c8a514ea5cced20eb6b5c8dec2368fa16bba618891b9a69b241965e14947","007395c473f26cfcb59ab5be0582d7c4eeff8b5c72abb3cb18b9036ef0578bb7","a50a4ee87a7bde63aa3a35edd3bdb9cf4c3af8759104dbb9af08b87126ab6a9a","c9ba76f88d66712c51a5a119d632f62bcaa732c2fa5c8462fe7915684e57ff67","f67fac478210657611e869e2362d223e4d61f917c070e8240e9a60986f4f8637","42d3551eccf74ddce49fc958867627299b20c5731d4574d5c0f6b9816280faa0","5e6077e37d029ce395176871abb5d9e7f57ee5081e795dd5b298230a647b0553","c3d442c17548ba48cf94807da3d921bc116a4ef290ce2cb3d250ca4908fbf288","555887e71cdaf0778cf5d0c7e3ff29e939eb936d1ea3ee41243c3953a27ce045","6e993216d537448a8c69aad1589937cbc7bf669170f4be096581b6bc6817c6ff","8c54633bd9f570d76382a2d9dc80bc22edd5ca6c328add090812475c6728ec64","2a04c5392e50c6130127a09e8e938c71bd434ec57561fd27c916cf9622476b02","21d40f8dedbedd15e1c8d8f9ee192113aea300fd301ae2d790c53d927004102f","a8ec6e7afa929f5b4b623b03caf71bc9f3da37db2ffe76834c8e8fdefc59849f","446f1e6d9689df03c60c5a304e40b7edbdf505f188a914c105f2e58e1e641698","2c984aa8ea779bc70295121d6b9345c1de3c1fbc785ab793407ceb723835ca02","50b16d3ba0174d213d96f10068a2a01835286e8ac965b25c5aa658c5e60bc11f","5c7c053f85a15696cb4d3d466f3f2151be10b8b5fb0670b44d5f064b8897cc1e","2c993e1ec6fbdd02a472028d5203809ef8f2c76c2bc274110a7b01926dfe2b8c","8dafcb5fb479acabc058b87fa4347cba6104f7e960522f560a5b97818bca48a5","78dd0065f3d11c46b4d77028bdb0c29ee0a736cfea9f8d80a7815a02e2abaf7f","c88d9f88f24fe30f65be0b070060a030464fe89447e508b8529524970cde6aa6","1ea9b70fb2a0fe796ffdb9131c0c2a34176375fa6a4a888e6db613089a7e6782","ef66473f8402eff2a1d498a5026b7c333e849431465b2fa09b001ae0bac21ace","3a54a9ef2660e17912988954069c5b4143cf8f75227c8d8bf8eed6d1d0afd49f","86c18f2c92063f5dae9b954ca61b9798b4e59a7aec23d7d66fa182e009d7d31a","739d47f59b244557f360604ddfcba5293e24de25c7e3fe84c6cf4961dc620b9c","1c9c6ddba8ecb02562d0822a5e3c37046177866a4079b4ca166b923b72edeb16",{"version":"79fec4fbe74b8c013dd5f5e783c7ae1bc25ad38be5529f716168f47417e32203","affectsGlobalScope":true},{"version":"36fe69661e343cb4be10ff09db41af3abed1309a5edcb089e2e001f3c935efaf","affectsGlobalScope":true}],"root":[[50,115]],"options":{"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"declarationMap":true,"experimentalDecorators":true,"importHelpers":true,"inlineSources":true,"module":5,"noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitOverride":true,"noImplicitReturns":true,"noImplicitThis":true,"noUnusedLocals":true,"noUnusedParameters":true,"outDir":"./lib","rootDir":"./src","sourceMap":true,"strict":true,"stripInternal":true,"target":8},"fileIdsList":[[73,74,75,79,80,81,82,83,84,85,86],[88,89],[91,92],[94,95,96],[87,90,93,97,98,102,110],[78],[83],[82],[77],[91],[78,89],[94],[76,77,78,88],[76,77],[103],[77,103],[103,106],[77,78,88,103],[103,108],[76,77,78],[99,100,101],[103,104,105,106,107,108,109],[73,74,75,76,77,78,79,80,81,82,83,84,85,86,88,89,91,92,99,100,101,103,104,105,106,107,108,109],[76,77,78,79,80,81,88,89,94,95,96,101],[114],[57,69],[51,53],[51],[50,51,52,53,54],[50,52,54,56,57,71],[50,52,55,56],[61],[66],[61,65],[60],[58,59,60,61,62,63,64,65,66,67,68],[50,51,52,53],[50,56]],"referencedMap":[[87,1],[90,2],[93,3],[97,4],[111,5],[79,6],[80,6],[81,6],[84,7],[85,8],[86,7],[88,9],[92,10],[91,11],[95,12],[96,12],[94,13],[78,14],[104,15],[105,16],[107,17],[106,18],[109,19],[108,16],[98,20],[102,21],[110,22],[112,23],[113,24],[115,25],[70,26],[54,27],[52,28],[55,29],[72,30],[57,31],[62,32],[63,32],[64,32],[67,33],[66,34],[61,35],[69,36]],"exportedModulesMap":[[87,1],[90,2],[93,3],[97,4],[111,5],[79,6],[80,6],[81,6],[84,7],[85,8],[86,7],[88,9],[92,10],[91,11],[95,12],[96,12],[94,13],[78,14],[104,15],[105,16],[107,17],[106,18],[109,19],[108,16],[98,20],[102,21],[110,22],[112,23],[113,24],[115,25],[54,27],[52,28],[55,37],[72,30],[57,38],[62,32],[63,32],[64,32],[67,33],[66,34],[61,35],[69,36]],"semanticDiagnosticsPerFile":[87,90,93,97,111,73,74,75,79,80,81,82,83,84,85,86,88,89,92,91,95,96,94,76,77,78,99,100,101,104,105,103,107,106,109,108,98,102,110,112,113,115,114,48,49,10,9,2,11,12,13,14,15,16,17,18,3,19,4,20,24,21,22,23,25,26,27,5,28,29,30,31,6,35,32,33,34,36,7,37,42,43,38,39,40,41,8,47,44,45,46,1,70,54,51,53,50,52,55,72,71,57,56,58,59,62,63,64,65,67,66,60,61,68,69],"latestChangedDtsFile":"./lib/openapi-client/index.d.ts"},"version":"5.4.5"}
\ No newline at end of file
diff --git a/typescript/packages/usuba-ui/index.html b/typescript/packages/usuba-ui/index.html
index 1f042f847..7a1971c5a 100644
--- a/typescript/packages/usuba-ui/index.html
+++ b/typescript/packages/usuba-ui/index.html
@@ -7,7 +7,7 @@
Usuba
-
+
@@ -27,6 +27,9 @@
+ special btn
+
+
diff --git a/typescript/packages/usuba-ui/package.json b/typescript/packages/usuba-ui/package.json
index af360375a..2dc728c4d 100644
--- a/typescript/packages/usuba-ui/package.json
+++ b/typescript/packages/usuba-ui/package.json
@@ -7,7 +7,8 @@
"private": true,
"type": "module",
"scripts": {
- "build": "wireit"
+ "build": "wireit",
+ "clean": "wireit"
},
"repository": {
"type": "git",
@@ -22,6 +23,7 @@
},
"devDependencies": {
"@commontools/usuba-sw": "^0.0.1",
+ "@commontools/usuba-api": "^0.0.1",
"typescript": "^5.2.2",
"vite": "^5.2.0",
"wireit": "^0.14.4"
@@ -29,9 +31,13 @@
"wireit": {
"build": {
"dependencies": [
+ "../usuba-rt:build",
"../usuba-sw:build"
],
- "command": "vite build"
+ "command": "vite build && mv ./dist/index.html ./dist/$.html"
+ },
+ "clean": {
+ "command": "rm -rf ./lib ./dist ./.wireit"
}
}
-}
+}
\ No newline at end of file
diff --git a/typescript/packages/usuba-ui/public/usuba-ui/styles.css b/typescript/packages/usuba-ui/public/usuba-ui/styles.css
new file mode 100644
index 000000000..952318d3d
--- /dev/null
+++ b/typescript/packages/usuba-ui/public/usuba-ui/styles.css
@@ -0,0 +1,36 @@
+body {
+ font-family: var(--sl-font-sans, sans-serif);
+ padding: 1em;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+sl-textarea {
+ min-height: 360px;
+ flex: 1;
+}
+sl-textarea::part(textarea) {
+ font-family: var(--sl-font-mono, mono);
+ font-size: 0.85rem;
+}
+
+sl-input {
+ flex: 1;
+}
+
+#specifier {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ margin-bottom: 1em;
+ gap: 1em;
+ margin-right: 1em;
+}
+
+#code {
+ display: flex;
+ flex-direction: row;
+ gap: 1em;
+}
\ No newline at end of file
diff --git a/typescript/packages/usuba-ui/public/wasi.js b/typescript/packages/usuba-ui/public/wasi.js
new file mode 100644
index 000000000..46f863bd0
--- /dev/null
+++ b/typescript/packages/usuba-ui/public/wasi.js
@@ -0,0 +1,17 @@
+import * as cli from '/wasi-shim/cli.js';
+import * as clocks from '/wasi-shim/clocks.js';
+import * as filesystem from '/wasi-shim/filesystem.js';
+import * as http from '/wasi-shim/http.js';
+import * as io from '/wasi-shim/io.js';
+import * as random from '/wasi-shim/random.js';
+import * as sockets from '/wasi-shim/sockets.js';
+
+export const shim = {
+ '/wasi-shim/cli.js': Promise.resolve(cli),
+ '/wasi-shim/clocks.js': Promise.resolve(clocks),
+ '/wasi-shim/filesystem.js': Promise.resolve(filesystem),
+ '/wasi-shim/http.js': Promise.resolve(http),
+ '/wasi-shim/io.js': Promise.resolve(io),
+ '/wasi-shim/random.js': Promise.resolve(random),
+ '/wasi-shim/sockets.js': Promise.resolve(sockets),
+};
\ No newline at end of file
diff --git a/typescript/packages/usuba-ui/src/index.ts b/typescript/packages/usuba-ui/src/index.ts
index c07176ba8..e177c5f2d 100644
--- a/typescript/packages/usuba-ui/src/index.ts
+++ b/typescript/packages/usuba-ui/src/index.ts
@@ -9,10 +9,11 @@ import type SlTextarea from '@shoelace-style/shoelace/dist/components/textarea/t
import type SlInput from '@shoelace-style/shoelace/dist/components/input/input.js';
import type SlCopyButton from '@shoelace-style/shoelace/dist/components/copy-button/copy-button.js';
import type SlSelect from '@shoelace-style/shoelace/dist/components/select/select.js';
+import * as apiClient from '@commontools/usuba-api';
setBasePath('/shoelace/dist');
-const $ = (s) => document.querySelector(s);
+const $ = (s: string) => document.querySelector(s);
const witTextArea = $('sl-textarea[label="WIT"]') as SlTextarea;
const sourceCodeTextArea = $('sl-textarea[label="Source Code"]') as SlTextarea;
@@ -45,3 +46,33 @@ const updateSpecifier = () => {
};
updateSpecifier();
+
+// $('sl-button')!.addEventListener('click', async () => {
+// console.log('Lfgggg');
+// const result = await apiClient.buildModule({
+// formData: {
+// library: [],
+// module: [
+// new File(
+// [new Blob([witTextArea.value], { type: 'text/plain' })],
+// 'module.wit'
+// ),
+// new File(
+// [new Blob([sourceCodeTextArea.value], { type: 'text/javascript' })],
+// 'module.js'
+// ),
+// ],
+// },
+// });
+// console.log('DONE!', result);
+
+// const { instantiate } = await import(
+// /* @vite-ignore */ `/module/transpiled/runtime/${result.id}.js`
+// );
+
+// console.log(instantiate);
+
+// const { hello } = await instantiate({});
+
+// console.log(hello());
+// });
diff --git a/typescript/packages/usuba-ui/tsconfig.json b/typescript/packages/usuba-ui/tsconfig.json
new file mode 100644
index 000000000..df767e62f
--- /dev/null
+++ b/typescript/packages/usuba-ui/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "lib": ["es2022", "DOM"],
+ "outDir": "./lib",
+ "rootDir": "./src",
+ },
+ "include": [
+ "src/**/*"
+ ]
+}
diff --git a/typescript/packages/usuba-ui/vite.config.js b/typescript/packages/usuba-ui/vite.config.js
index edb6fa879..c5a2dd64c 100644
--- a/typescript/packages/usuba-ui/vite.config.js
+++ b/typescript/packages/usuba-ui/vite.config.js
@@ -3,6 +3,7 @@ import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
+ base: '',
build: {
target: 'esnext'
},
diff --git a/typescript/tsconfig.base.json b/typescript/tsconfig.base.json
new file mode 100644
index 000000000..3a0c2422f
--- /dev/null
+++ b/typescript/tsconfig.base.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "target": "es2022",
+ "module": "NodeNext",
+ "lib": ["es2022"],
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "inlineSources": true,
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "moduleResolution": "NodeNext",
+ "allowSyntheticDefaultImports": true,
+ "experimentalDecorators": true,
+ "importHelpers": true,
+ "stripInternal": true,
+ "noImplicitOverride": true,
+ "skipLibCheck": true,
+ "types": []
+ },
+ "include": [
+ "src/**/*"
+ ]
+}