lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit 2e65f6dd94d6e7e9b5bc78fe83efaf320af62179
parent b5ddc8fd1c926a1f04f8e505ee0ac8174e6a390b
Author: triesap <tyson@radroots.org>
Date:   Thu, 13 Nov 2025 01:03:28 +0000

workspace: add `tangle-sql-wasm` crate and wasm build pipeline

Diffstat:
MCargo.lock | 23+++++++++++++++++++++++
MCargo.toml | 4++++
MMakefile | 44++++++++++++++++++++++++++++++--------------
Msql-core/src/lib.rs | 6+++---
Atangle-sql-wasm/Cargo.toml | 20++++++++++++++++++++
Atangle-sql-wasm/pkg/package.json | 17+++++++++++++++++
Atangle-sql-wasm/src/lib.rs | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atangle-sql-wasm/src/utils.rs | 40++++++++++++++++++++++++++++++++++++++++
8 files changed, 197 insertions(+), 17 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -1862,6 +1862,29 @@ dependencies = [ ] [[package]] +name = "radroots-tangle-sql" +version = "0.1.0" +dependencies = [ + "radroots-sql-core", + "radroots-tangle-schema", + "serde_json", +] + +[[package]] +name = "radroots-tangle-sql-wasm" +version = "0.1.0" +dependencies = [ + "radroots-sql-core", + "radroots-sql-wasm-core", + "radroots-tangle-schema", + "radroots-tangle-sql", + "serde", + "serde-wasm-bindgen", + "serde_json", + "wasm-bindgen", +] + +[[package]] name = "radroots-trade" version = "0.1.0" dependencies = [ diff --git a/Cargo.toml b/Cargo.toml @@ -14,6 +14,8 @@ members = [ "sql-wasm-core", "sql-core", "tangle-schema", + "tangle-sql", + "tangle-sql-wasm", "trade", "types", ] @@ -40,6 +42,8 @@ radroots-sql-wasm-bridge = { path = "sql-wasm-bridge", version = "0.1.0" } radroots-sql-wasm-core = { path = "sql-wasm-core", version = "0.1.0" } radroots-sql-core = { path = "sql-core", version = "0.1.0" } radroots-tangle-schema = { path = "tangle-schema", version = "0.1.0", default-features = false } +radroots-tangle-sql = { path = "tangle-sql", version = "0.1.0", default-features = false } +radroots-tangle-sql-wasm = { path = "tangle-sql-wasm", version = "0.1.0" } radroots-trade = { path = "trade", version = "0.1.0", default-features = false } radroots-types = { path = "types", version = "0.1.0", default-features = false } diff --git a/Makefile b/Makefile @@ -1,28 +1,44 @@ -.PHONY: all bindings bindings-tangle-schema bindings-types clean help +.PHONY: all bindings clean help \ + bindings-tangle-schema bindings-types \ + build build-tangle-sql-wasm + SHELL := /bin/bash .SHELLFLAGS := -e -o pipefail -c TS_RS_FEATURE ?= ts-rs -all: bindings +BINDINGS_TARGETS := \ + bindings-tangle-schema \ + bindings-types + +BUILD_TARGETS := \ + build-tangle-sql-wasm + +all: bindings build + +bindings: $(BINDINGS_TARGETS) -bindings: bindings-tangle-schema bindings-types - @echo "All bindings built successfully." +build: $(BUILD_TARGETS) + +clean: + cargo clean + +help: + @echo "Commands:" + @echo " make all" + @echo " make bindings" + @echo " make build" + @echo " make clean" + @echo " make help" + @printf "%s\n" $(BINDINGS_TARGETS) + @printf "%s\n" $(BUILD_TARGETS) bindings-tangle-schema: - @echo "Building tangle-schema bindings" @(cd tangle-schema && cargo test --features $(TS_RS_FEATURE)) @(cd tangle-schema/bindings/ts && yarn build) bindings-types: - @echo "Building types bindings" @(cd types && cargo test --features $(TS_RS_FEATURE)) @(cd types/bindings/ts && yarn build) -clean: - cargo clean - -help: - @echo "Usage:" - @echo " make bindings Build all Rust + TS bindings for all crates" - @echo " make clean Remove build artifacts" - @echo " make help Show this help message" +build-tangle-sql-wasm: + wasm-pack build tangle-sql-wasm --release --target web --out-dir ../tangle-sql-wasm/pkg/dist --scope radroots diff --git a/sql-core/src/lib.rs b/sql-core/src/lib.rs @@ -5,9 +5,9 @@ extern crate alloc; pub mod error; -#[cfg(feature = "web")] +#[cfg(all(feature = "web", target_arch = "wasm32"))] mod executor_wasm; -#[cfg(feature = "web")] +#[cfg(all(feature = "web", target_arch = "wasm32"))] pub use executor_wasm::WasmSqlExecutor; #[cfg(feature = "native")] @@ -23,7 +23,7 @@ pub use executor_embedded::EmbeddedSqlExecutor; #[cfg(not(any(feature = "embedded", target_os = "espidf")))] pub mod utils; -use error::SqlError; +pub use error::SqlError; #[derive(Clone, Copy, Debug)] pub struct ExecOutcome { diff --git a/tangle-sql-wasm/Cargo.toml b/tangle-sql-wasm/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "radroots-tangle-sql-wasm" +version.workspace = true +edition.workspace = true +authors = ["Radroots Authors"] +rust-version.workspace = true +license.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +radroots-sql-core = { workspace = true, features = ["web"] } +radroots-sql-wasm-core = { workspace = true } +radroots-tangle-sql = { workspace = true } +radroots-tangle-schema = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +serde-wasm-bindgen = { workspace = true } +wasm-bindgen = { workspace = true } diff --git a/tangle-sql-wasm/pkg/package.json b/tangle-sql-wasm/pkg/package.json @@ -0,0 +1,16 @@ +{ + "name": "@radroots/tangle-sql-wasm", + "version": "0.1.0", + "private": true, + "type": "module", + "files": [ + "dist" + ], + "exports": { + ".": { + "types": "./dist/radroots_tangle_sql_wasm.d.ts", + "import": "./dist/radroots_tangle_sql_wasm.js" + } + }, + "sideEffects": false +} +\ No newline at end of file diff --git a/tangle-sql-wasm/src/lib.rs b/tangle-sql-wasm/src/lib.rs @@ -0,0 +1,60 @@ +#![cfg(target_arch = "wasm32")] + +use wasm_bindgen::prelude::*; + +use radroots_sql_core::WasmSqlExecutor; +use radroots_tangle_schema::log_error::{ + ILogErrorFields, ILogErrorFieldsFilter, ILogErrorFieldsPartial, LogError, + LogErrorQueryBindValues, +}; +use radroots_tangle_sql::log_error; + +pub mod utils; +pub use utils::*; + +#[wasm_bindgen(js_name = tangle_log_error_create)] +pub fn tangle_log_error_create(opts_json: &str) -> Result<JsValue, JsValue> { + let payload = radroots_sql_wasm_core::parse_json::<ILogErrorFields>(opts_json) + .map_err(radroots_sql_wasm_core::err_js)?; + let exec = WasmSqlExecutor::new(); + let out = log_error::insert(&exec, payload).map_err(radroots_sql_wasm_core::err_js)?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = tangle_log_error_find_many)] +pub fn tangle_log_error_find_many(filter_json: &str) -> Result<JsValue, JsValue> { + let filter = parse_optional_json::<ILogErrorFieldsFilter>(filter_json) + .map_err(radroots_sql_wasm_core::err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + log_error::find_many(&exec, filter.as_ref()).map_err(radroots_sql_wasm_core::err_js)?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = tangle_log_error_find_one)] +pub fn tangle_log_error_find_one(bind_json: &str) -> Result<JsValue, JsValue> { + let bind = radroots_sql_wasm_core::parse_json::<LogErrorQueryBindValues>(bind_json) + .map_err(radroots_sql_wasm_core::err_js)?; + let exec = WasmSqlExecutor::new(); + let out: Option<LogError> = + log_error::find_one(&exec, &bind).map_err(radroots_sql_wasm_core::err_js)?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = tangle_log_error_update)] +pub fn tangle_log_error_update(id: &str, fields_json: &str) -> Result<JsValue, JsValue> { + let fields = radroots_sql_wasm_core::parse_json::<ILogErrorFieldsPartial>(fields_json) + .map_err(radroots_sql_wasm_core::err_js)?; + let exec = WasmSqlExecutor::new(); + let outcome = log_error::update(&exec, id, fields).map_err(radroots_sql_wasm_core::err_js)?; + outcome_to_js(outcome) +} + +#[wasm_bindgen(js_name = tangle_log_error_delete)] +pub fn tangle_log_error_delete(bind_json: &str) -> Result<JsValue, JsValue> { + let bind = radroots_sql_wasm_core::parse_json::<LogErrorQueryBindValues>(bind_json) + .map_err(radroots_sql_wasm_core::err_js)?; + let exec = WasmSqlExecutor::new(); + let outcome = log_error::delete(&exec, &bind).map_err(radroots_sql_wasm_core::err_js)?; + outcome_to_js(outcome) +} diff --git a/tangle-sql-wasm/src/utils.rs b/tangle-sql-wasm/src/utils.rs @@ -0,0 +1,40 @@ +use radroots_sql_core::error::SqlError; +use serde::de::DeserializeOwned; +use serde_json::json; +use wasm_bindgen::JsValue; + +pub fn parse_optional_json<T>(input: &str) -> Result<Option<T>, SqlError> +where + T: DeserializeOwned, +{ + let trimmed = input.trim(); + if trimmed.is_empty() || trimmed == "null" { + Ok(None) + } else { + let value = radroots_sql_wasm_core::parse_json::<T>(trimmed)?; + Ok(Some(value)) + } +} + +fn serialize_to_js_value<T>(value: &T) -> Result<JsValue, JsValue> +where + T: serde::Serialize, +{ + serde_wasm_bindgen::to_value(value) + .map_err(|e| radroots_sql_wasm_core::err_js(SqlError::SerializationError(e.to_string()))) +} + +pub fn outcome_to_js(outcome: radroots_sql_core::ExecOutcome) -> Result<JsValue, JsValue> { + let payload = json!({ + "changes": outcome.changes, + "last_insert_id": outcome.last_insert_id, + }); + serialize_to_js_value(&payload) +} + +pub fn value_to_js<T>(value: T) -> Result<JsValue, JsValue> +where + T: serde::Serialize, +{ + serialize_to_js_value(&value) +}