lib

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

commit ec5e59445a0e475ef3b41040d98cdaaaa1f498b0
parent cb167a7004167bf131efcb0a5e9815e35ad756c2
Author: triesap <tyson@radroots.org>
Date:   Thu, 19 Feb 2026 18:24:32 +0000

nostr-ndb: add runtime event store adapter


- add an ndb-backed event store adapter for runtime integration
- implement runtime trait ingestion for default client-origin events
- support configurable relay or client source behavior on the adapter
- add unit tests for adapter ingestion and trait object usage

Diffstat:
Mnostr-ndb/src/lib.rs | 4++++
Anostr-ndb/src/runtime_adapter.rs | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/nostr-ndb/src/lib.rs b/nostr-ndb/src/lib.rs @@ -13,6 +13,8 @@ pub mod error; pub mod ingest; #[cfg(feature = "ndb")] pub mod ndb; +#[cfg(all(feature = "ndb", feature = "runtime-adapter"))] +pub mod runtime_adapter; pub mod prelude { #[cfg(feature = "ndb")] @@ -22,4 +24,6 @@ pub mod prelude { pub use crate::ingest::RadrootsNostrNdbIngestSource; #[cfg(feature = "ndb")] pub use crate::ndb::RadrootsNostrNdb; + #[cfg(all(feature = "ndb", feature = "runtime-adapter"))] + pub use crate::runtime_adapter::RadrootsNostrNdbEventStoreAdapter; } diff --git a/nostr-ndb/src/runtime_adapter.rs b/nostr-ndb/src/runtime_adapter.rs @@ -0,0 +1,90 @@ +use crate::ingest::RadrootsNostrNdbIngestSource; +use crate::ndb::RadrootsNostrNdb; +use radroots_nostr::prelude::RadrootsNostrEvent; +use radroots_nostr_runtime::prelude::RadrootsNostrEventStore; +use std::sync::Arc; + +#[derive(Clone)] +pub struct RadrootsNostrNdbEventStoreAdapter { + ndb: RadrootsNostrNdb, + source: RadrootsNostrNdbIngestSource, +} + +impl RadrootsNostrNdbEventStoreAdapter { + pub fn new(ndb: RadrootsNostrNdb) -> Self { + Self { + ndb, + source: RadrootsNostrNdbIngestSource::client(), + } + } + + pub fn with_source(mut self, source: RadrootsNostrNdbIngestSource) -> Self { + self.source = source; + self + } + + pub fn into_event_store(self) -> Arc<dyn RadrootsNostrEventStore> { + Arc::new(self) + } +} + +impl RadrootsNostrEventStore for RadrootsNostrNdb { + fn ingest_event(&self, event: &RadrootsNostrEvent) -> Result<(), String> { + RadrootsNostrNdb::ingest_event(self, event, RadrootsNostrNdbIngestSource::client()) + .map_err(|source| source.to_string()) + } +} + +impl RadrootsNostrEventStore for RadrootsNostrNdbEventStoreAdapter { + fn ingest_event(&self, event: &RadrootsNostrEvent) -> Result<(), String> { + self.ndb + .ingest_event(event, self.source.clone()) + .map_err(|source| source.to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::config::RadrootsNostrNdbConfig; + use radroots_nostr::prelude::{RadrootsNostrEventBuilder, RadrootsNostrKeys}; + use tempfile::TempDir; + + #[test] + fn runtime_adapter_accepts_signed_events() { + let tmp_dir = TempDir::new().expect("tempdir should open"); + let db_dir = tmp_dir.path().join("ndb"); + let config = RadrootsNostrNdbConfig::new(&db_dir); + let ndb = RadrootsNostrNdb::open(config).expect("database should open"); + let adapter = RadrootsNostrNdbEventStoreAdapter::new(ndb); + + let keys = RadrootsNostrKeys::generate(); + let event = RadrootsNostrEventBuilder::text_note("hello from runtime adapter") + .sign_with_keys(&keys) + .expect("event should sign"); + + adapter + .ingest_event(&event) + .expect("adapter should ingest event"); + } + + #[test] + fn runtime_adapter_can_be_boxed_as_store_trait() { + let tmp_dir = TempDir::new().expect("tempdir should open"); + let db_dir = tmp_dir.path().join("ndb"); + let config = RadrootsNostrNdbConfig::new(&db_dir); + let ndb = RadrootsNostrNdb::open(config).expect("database should open"); + let store = RadrootsNostrNdbEventStoreAdapter::new(ndb) + .with_source(RadrootsNostrNdbIngestSource::relay("wss://relay.radroots.org")) + .into_event_store(); + + let keys = RadrootsNostrKeys::generate(); + let event = RadrootsNostrEventBuilder::text_note("hello trait object") + .sign_with_keys(&keys) + .expect("event should sign"); + + store + .ingest_event(&event) + .expect("boxed store should ingest event"); + } +}