commit 19bd9b31889a511f251aca09bde59922db558540
parent 985b55bd4b77d2dcb7e422389a92ab5756ad314b
Author: triesap <tyson@radroots.org>
Date: Thu, 11 Jun 2026 16:04:16 -0700
field: normalize imported field crate workspace
Diffstat:
18 files changed, 35 insertions(+), 353 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -1,25 +1,40 @@
[workspace]
members = [
- "crates/*",
+ "crates/field_core",
+ "crates/field_ffi_swift",
+ "crates/field_wasm",
]
resolver = "2"
[workspace.package]
-version = "0.1.0"
+version = "0.1.0-alpha.1"
edition = "2024"
-rust-version = "1.88.0"
+rust-version = "1.92.0"
license = "AGPL-3.0"
+repository = "https://github.com/radrootslabs/field_lib"
+homepage = "https://radroots.org"
+readme = "README"
[workspace.dependencies]
-radroots-app = { path = "crates/app" }
-radroots-app-ffi = { path = "crates/ffi" }
-radroots-log = { path = "../../crates/crates/log" }
-radroots-net-core = { path = "../../crates/crates/net-core"}
+radroots_field_core = { path = "crates/field_core", version = "0.1.0-alpha.1", default-features = false }
+radroots_field_ffi_swift = { path = "crates/field_ffi_swift", version = "0.1.0-alpha.1" }
+radroots_field_wasm = { path = "crates/field_wasm", version = "0.1.0-alpha.1" }
+radroots-core = { package = "radroots_core", path = "../lib/crates/core", version = "0.1.0-alpha.2", default-features = false }
+radroots-events = { package = "radroots_events", path = "../lib/crates/events", version = "0.1.0-alpha.2", default-features = false }
+radroots-events-codec = { package = "radroots_events_codec", path = "../lib/crates/events_codec", version = "0.1.0-alpha.2", default-features = false }
+radroots-identity = { package = "radroots_identity", path = "../lib/crates/identity", version = "0.1.0-alpha.2", default-features = false }
+radroots-log = { package = "radroots_log", path = "../lib/crates/log", version = "0.1.0-alpha.2", default-features = false }
+radroots-net-core = { package = "radroots_net", path = "../lib/crates/net", version = "0.1.0-alpha.2", default-features = false }
+radroots-nostr = { package = "radroots_nostr", path = "../lib/crates/nostr", version = "0.1.0-alpha.2", default-features = false }
+radroots-trade = { package = "radroots_trade", path = "../lib/crates/trade", version = "0.1.0-alpha.2", default-features = false }
chrono = { version = "0.4" }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1" }
thiserror = { version = "1" }
+tokio = { version = "1" }
tracing = { version = "0.1" }
+tracing-subscriber = { version = "0.3" }
uniffi = { version = "0.29.4" }
uniffi_build = { version = "0.29.4" }
+wasm-bindgen = { version = "0.2" }
diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml
@@ -1,20 +0,0 @@
-[package]
-name = "radroots-app"
-version.workspace = true
-edition.workspace = true
-authors = ["Radroots Authors"]
-rust-version.workspace = true
-license.workspace = true
-
-[lib]
-crate-type = ["rlib"]
-
-[dependencies]
-radroots-log = { workspace = true }
-radroots-net-core = { workspace = true, features = ["rt"] }
-chrono = { workspace = true }
-serde = { workspace = true, features = ["derive"] }
-serde_json = { workspace = true }
-thiserror = { workspace = true }
-tracing = { workspace = true }
-uniffi = { workspace = true }
-\ No newline at end of file
diff --git a/crates/app/build.rs b/crates/app/build.rs
@@ -1,53 +0,0 @@
-use std::{
- env,
- process::Command,
- time::{SystemTime, UNIX_EPOCH},
-};
-
-fn main() {
- println!("cargo:rerun-if-changed=build.rs");
- println!("cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH");
- println!("cargo:rerun-if-env-changed=PROFILE");
-
- let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into());
- if let Ok(out) = Command::new(rustc).arg("--version").output() {
- if out.status.success() {
- if let Ok(ver) = String::from_utf8(out.stdout) {
- println!("cargo:rustc-env=RUSTC_VERSION={}", ver.trim());
- }
- }
- }
-
- if let Ok(out) = Command::new("git")
- .args(["rev-parse", "--short=12", "HEAD"])
- .output()
- {
- if out.status.success() {
- let mut sha = String::from_utf8_lossy(&out.stdout).trim().to_string();
- let dirty = Command::new("git")
- .args(["status", "--porcelain"])
- .output()
- .ok()
- .map_or(false, |o| o.status.success() && !o.stdout.is_empty());
- if dirty {
- sha.push_str("-dirty");
- }
- println!("cargo:rustc-env=GIT_HASH={sha}");
- }
- }
-
- if let Ok(profile) = env::var("PROFILE") {
- println!("cargo:rustc-env=PROFILE={profile}");
- }
-
- let epoch = env::var("SOURCE_DATE_EPOCH")
- .ok()
- .and_then(|v| v.parse::<u64>().ok())
- .unwrap_or_else(|| {
- SystemTime::now()
- .duration_since(UNIX_EPOCH)
- .map(|d| d.as_secs())
- .unwrap_or(0)
- });
- println!("cargo:rustc-env=BUILD_TIME_UNIX={epoch}");
-}
diff --git a/crates/app/src/error.rs b/crates/app/src/error.rs
@@ -1,7 +0,0 @@
-use thiserror::Error;
-
-#[derive(Debug, Error, uniffi::Error)]
-pub enum RadrootsAppError {
- #[error("{0}")]
- Msg(String),
-}
diff --git a/crates/app/src/lib.rs b/crates/app/src/lib.rs
@@ -1,10 +0,0 @@
-uniffi::setup_scaffolding!("radroots");
-
-pub mod error;
-pub mod logging;
-pub mod runtime;
-
-pub use error::RadrootsAppError;
-pub use radroots_net_core::net::{BuildInfo, NetInfo};
-pub use radroots_net_core::{Net, NetHandle};
-pub use runtime::RadrootsRuntime;
diff --git a/crates/app/src/logging.rs b/crates/app/src/logging.rs
@@ -1,38 +0,0 @@
-use std::path::PathBuf;
-
-#[uniffi::export]
-pub fn init_logging(
- dir: Option<String>,
- file_name: Option<String>,
- is_stdout: Option<bool>,
-) -> Result<(), crate::RadrootsAppError> {
- let opts = radroots_log::LoggingOptions {
- dir: dir.map(PathBuf::from),
- file_name: file_name.unwrap_or_else(|| "radroots.log".to_string()),
- stdout: is_stdout.unwrap_or(true),
- };
- radroots_log::init_logging(opts).map_err(|e| crate::RadrootsAppError::Msg(format!("{e}")))
-}
-
-#[uniffi::export]
-pub fn init_logging_stdout() -> Result<(), crate::RadrootsAppError> {
- radroots_log::init_stdout().map_err(|e| crate::RadrootsAppError::Msg(format!("{e}")))
-}
-
-#[uniffi::export]
-pub fn log_info(msg: String) -> Result<(), crate::RadrootsAppError> {
- radroots_log::log_info(msg);
- Ok(())
-}
-
-#[uniffi::export]
-pub fn log_error(msg: String) -> Result<(), crate::RadrootsAppError> {
- radroots_log::log_error(msg);
- Ok(())
-}
-
-#[uniffi::export]
-pub fn log_debug(msg: String) -> Result<(), crate::RadrootsAppError> {
- radroots_log::log_debug(msg);
- Ok(())
-}
diff --git a/crates/app/src/runtime.rs b/crates/app/src/runtime.rs
@@ -1,176 +0,0 @@
-use chrono::Utc;
-use radroots_net_core::{NetHandle, builder::NetBuilder, net};
-use serde::Serialize;
-use std::sync::{
- RwLock,
- atomic::{AtomicBool, Ordering},
-};
-use tracing::info;
-
-#[inline]
-fn is_false(b: &bool) -> bool {
- !*b
-}
-
-#[derive(Debug, Clone, Serialize, Default, uniffi::Record)]
-pub struct NetBuildInfo {
- pub crate_name: String,
- pub crate_version: String,
- pub rustc: Option<String>,
- pub profile: Option<String>,
- pub git_sha: Option<String>,
- pub build_time_unix: Option<u64>,
-}
-
-impl From<&net::BuildInfo> for NetBuildInfo {
- fn from(b: &net::BuildInfo) -> Self {
- Self {
- crate_name: b.crate_name.to_string(),
- crate_version: b.crate_version.to_string(),
- rustc: b.rustc.map(|s| s.to_string()),
- profile: b.profile.map(|s| s.to_string()),
- git_sha: b.git_sha.map(|s| s.to_string()),
- build_time_unix: b.build_time_unix,
- }
- }
-}
-
-#[derive(Debug, Clone, Serialize, Default, uniffi::Record)]
-pub struct AppInfoPlatform {
- pub platform: Option<String>,
- pub bundle_id: Option<String>,
- pub version: Option<String>,
- pub build_number: Option<String>,
- pub build_sha: Option<String>,
-}
-
-pub type AppBuildInfo = NetBuildInfo;
-
-#[derive(Debug, Clone, Serialize, uniffi::Record)]
-pub struct AppInfo {
- pub build: AppBuildInfo,
- pub platform: Option<AppInfoPlatform>,
- pub started_unix_ms: i64,
- pub uptime_millis: i64,
- #[serde(skip_serializing_if = "is_false")]
- pub shutting_down: bool,
-}
-
-#[derive(Debug, Clone, Serialize, uniffi::Record)]
-pub struct RuntimeInfo {
- pub app: AppInfo,
- pub net: NetBuildInfo,
-}
-
-#[derive(uniffi::Object)]
-pub struct RadrootsRuntime {
- net: NetHandle,
- started_unix_ms: i64,
- shutting_down: AtomicBool,
- platform_app: RwLock<Option<AppInfoPlatform>>,
-}
-
-impl RadrootsRuntime {
- fn app_build_info() -> NetBuildInfo {
- NetBuildInfo {
- crate_name: env!("CARGO_PKG_NAME").to_string(),
- crate_version: env!("CARGO_PKG_VERSION").to_string(),
- rustc: option_env!("RUSTC_VERSION").map(|s| s.to_string()),
- profile: option_env!("PROFILE").map(|s| s.to_string()),
- git_sha: option_env!("GIT_HASH").map(|s| s.to_string()),
- build_time_unix: option_env!("BUILD_TIME_UNIX").and_then(|s| s.parse().ok()),
- }
- }
-
- fn uptime_millis_from(&self, now_ms: i64) -> i64 {
- now_ms.saturating_sub(self.started_unix_ms)
- }
-}
-
-#[uniffi::export]
-impl RadrootsRuntime {
- #[uniffi::constructor]
- pub fn new() -> Result<Self, crate::RadrootsAppError> {
- let cfg = radroots_net_core::config::NetConfig::default();
- let handle = NetBuilder::new()
- .config(cfg)
- .manage_runtime(true)
- .build()
- .map_err(|e| crate::RadrootsAppError::Msg(format!("net build failed: {e}")))?;
-
- Ok(Self {
- net: handle,
- started_unix_ms: Utc::now().timestamp_millis(),
- shutting_down: AtomicBool::new(false),
- platform_app: RwLock::new(None),
- })
- }
-
- pub fn set_app_info_platform(
- &self,
- platform: Option<String>,
- bundle_id: Option<String>,
- version: Option<String>,
- build_number: Option<String>,
- build_sha: Option<String>,
- ) {
- let info = AppInfoPlatform {
- platform,
- bundle_id,
- version,
- build_number,
- build_sha,
- };
- if let Ok(mut guard) = self.platform_app.write() {
- *guard = Some(info);
- }
- }
-
- pub fn stop(&self) {
- if self
- .shutting_down
- .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
- .is_err()
- {
- info!("Runtime stop already in progress or completed.");
- return;
- }
-
- if let Ok(mut net) = self.net.lock() {
- if let Some(_rt) = net.rt.take() {
- info!("The runtime stopped gracefully.");
- } else {
- info!("No runtime was active at stop call.");
- }
- } else {
- info!("Failed to acquire runtime lock during stop.");
- }
- }
-
- pub fn uptime_millis(&self) -> i64 {
- self.uptime_millis_from(Utc::now().timestamp_millis())
- }
-
- pub fn info(&self) -> RuntimeInfo {
- let now_ms = Utc::now().timestamp_millis();
- let app = AppInfo {
- build: Self::app_build_info(),
- platform: self.platform_app.read().ok().and_then(|g| (*g).clone()),
- started_unix_ms: self.started_unix_ms,
- uptime_millis: self.uptime_millis_from(now_ms),
- shutting_down: self.shutting_down.load(Ordering::SeqCst),
- };
- let net = match self.net.lock() {
- Ok(guard) => NetBuildInfo::from(&guard.info.build),
- Err(_) => NetBuildInfo::default(),
- };
- RuntimeInfo { app, net }
- }
-
- pub fn info_json(&self) -> String {
- match serde_json::to_string_pretty(&self.info()) {
- Ok(s) => s,
- Err(e) => format!(r#"{{"error":"failed to serialize RuntimeInfo: {e}"}}"#),
- }
- }
-}
diff --git a/crates/ffi/Cargo.toml b/crates/ffi/Cargo.toml
@@ -1,21 +0,0 @@
-[package]
-name = "radroots-app-ffi"
-version.workspace = true
-edition.workspace = true
-authors = ["Radroots Authors"]
-rust-version.workspace = true
-license.workspace = true
-
-[lib]
-crate-type = ["staticlib", "cdylib"]
-
-[[bin]]
-name = "uniffi-bindgen"
-path = "bin/uniffi-bindgen.rs"
-
-[build-dependencies]
-uniffi_build = { workspace = true }
-
-[dependencies]
-radroots-app = { workspace = true }
-uniffi = { workspace = true, features = ["cli"] }
diff --git a/crates/ffi/bin/uniffi-bindgen.rs b/crates/ffi/bin/uniffi-bindgen.rs
@@ -1,3 +0,0 @@
-fn main() {
- uniffi::uniffi_bindgen_main()
-}
diff --git a/crates/ffi/src/lib.rs b/crates/ffi/src/lib.rs
@@ -1 +0,0 @@
-radroots_app::uniffi_reexport_scaffolding!();
diff --git a/crates/ffi/uniffi.toml b/crates/ffi/uniffi.toml
@@ -1,3 +0,0 @@
-[bindings.swift]
-module_name = "RadrootsKitBindings"
-ffi_module_name = "RadrootsFFI"
diff --git a/crates/field_core/Cargo.toml b/crates/field_core/Cargo.toml
@@ -5,7 +5,7 @@ edition.workspace = true
authors = ["Radroots Authors"]
rust-version.workspace = true
license.workspace = true
-description = "core application runtime primitives for radroots app surfaces"
+description = "core field runtime primitives for Radroots field surfaces"
repository.workspace = true
homepage.workspace = true
documentation = "https://docs.rs/radroots_field_core"
diff --git a/crates/field_core/README.md b/crates/field_core/README.md
@@ -1,13 +1,13 @@
# radroots_field_core
-Core application runtime primitives for Rad Roots app surfaces.
+Core field runtime primitives for Rad Roots field surfaces.
## Goals
-- define stable application runtime, error, and lifecycle interfaces
+- define stable field runtime, error, and lifecycle interfaces
- keep runtime and network wiring deterministic across supported targets
- support reusable integration points with `radroots-net-core`
-- provide reusable application primitives for higher-level Rad Roots crates
+- provide reusable field primitives for higher-level Rad Roots crates
## License
diff --git a/crates/field_core/src/logging.rs b/crates/field_core/src/logging.rs
@@ -9,6 +9,7 @@ pub fn init_logging(
let opts = radroots_log::LoggingOptions {
dir: dir.map(PathBuf::from),
file_name: file_name.unwrap_or_else(|| "radroots.log".to_string()),
+ file_layout: radroots_log::LogFileLayout::PrefixedDate,
stdout: is_stdout.unwrap_or(true),
default_level: None,
};
diff --git a/crates/field_wasm/Cargo.toml b/crates/field_wasm/Cargo.toml
@@ -5,7 +5,7 @@ edition.workspace = true
authors = ["Radroots Authors"]
rust-version.workspace = true
license.workspace = true
-description = "wasm application runtime bindings for radroots app surfaces"
+description = "wasm runtime bindings for Radroots field surfaces"
repository.workspace = true
homepage.workspace = true
documentation = "https://docs.rs/radroots_field_wasm"
diff --git a/crates/field_wasm/README.md b/crates/field_wasm/README.md
@@ -1,13 +1,13 @@
# radroots_field_wasm
-Wasm application runtime bindings for Rad Roots app surfaces.
+Wasm runtime bindings for Rad Roots field surfaces.
## Goals
- define stable wasm runtime interfaces for app metadata and startup
- keep wasm runtime behavior deterministic across supported browser targets
- support feature-gated bindings backed by `radroots_field_core`
-- provide reusable wasm entry points for higher-level Rad Roots app crates
+- provide reusable wasm entry points for higher-level Rad Roots field crates
## License
diff --git a/crates/field_wasm/src/lib.rs b/crates/field_wasm/src/lib.rs
@@ -3,7 +3,7 @@
use wasm_bindgen::prelude::wasm_bindgen;
#[wasm_bindgen]
-pub fn app_wasm_build_info_json() -> String {
+pub fn field_wasm_build_info_json() -> String {
let runtime = radroots_field_core::RadrootsRuntime::new()
.expect("runtime init must succeed with radroots_field_core no-default-features");
runtime.info_json()
@@ -15,11 +15,11 @@ pub fn coverage_branch_probe(input: bool) -> &'static str {
#[cfg(test)]
mod tests {
- use super::{app_wasm_build_info_json, coverage_branch_probe};
+ use super::{coverage_branch_probe, field_wasm_build_info_json};
#[test]
- fn app_wasm_build_info_json_contains_runtime_keys() {
- let json = app_wasm_build_info_json();
+ fn field_wasm_build_info_json_contains_runtime_keys() {
+ let json = field_wasm_build_info_json();
assert!(json.contains("\"app\""));
}
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
@@ -1,2 +1,2 @@
[toolchain]
-channel = "1.88.0"
-\ No newline at end of file
+channel = "1.92.0"