lib

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

commit 7faa57a39a16459e6bcd598d63ce900a414aa1bb
parent db352eac57658b672c6f2920693eaa92c7436ed2
Author: triesap <tyson@radroots.org>
Date:   Sat, 11 Jul 2026 23:56:26 +0000

crate-surface: rename SDK binding packages

- rename SDK binding and WASM crates to final event and replica surfaces
- regenerate TypeScript packages, provenance, and package metadata
- update xtask package matrix, WASM declarations, and SDK contracts
- remove retired types binding and replica db package surfaces without aliases

Diffstat:
Acrates/event_bindings/Cargo.toml | 14++++++++++++++
Acrates/event_bindings/src/lib.rs | 24++++++++++++++++++++++++
Acrates/event_bindings/src/model.rs | 192+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/event_codec_wasm/Cargo.toml | 38++++++++++++++++++++++++++++++++++++++
Acrates/event_codec_wasm/README | 24++++++++++++++++++++++++
Acrates/event_codec_wasm/src/lib.rs | 1732+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/replica_schema_bindings/Cargo.toml | 14++++++++++++++
Acrates/replica_schema_bindings/src/lib.rs | 31+++++++++++++++++++++++++++++++
Acrates/replica_store_wasm/Cargo.toml | 33+++++++++++++++++++++++++++++++++
Acrates/replica_store_wasm/README | 25+++++++++++++++++++++++++
Acrates/replica_store_wasm/src/lib.rs | 10++++++++++
Acrates/replica_store_wasm/src/snapshot.rs | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/replica_store_wasm/src/utils.rs | 13+++++++++++++
Acrates/replica_store_wasm/src/wasm_impl.rs | 914+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/sdk/Cargo.toml | 4++--
Mcrates/sdk/tests/replica_ingest.rs | 4++--
Mcrates/sdk/tests/runtime_foundation.rs | 2+-
Mcrates/sdk/tests/source_boundary.rs | 4++--
Mtools/sdk_xtask_import/Cargo.toml | 4++--
Mtools/sdk_xtask_import/src/check.rs | 8++++----
Mtools/sdk_xtask_import/src/contracts.rs | 70+++++++++++++++++++++++++++++++++++-----------------------------------
Mtools/sdk_xtask_import/src/dto_roots.rs | 220+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtools/sdk_xtask_import/src/output.rs | 54+++++++++++++++++++++++++-----------------------------
Mtools/sdk_xtask_import/src/package_matrix.rs | 62+++++++++++++++++++++++++++++++-------------------------------
Mtools/sdk_xtask_import/src/wasm.rs | 10+++++-----
Mtools/sdk_xtask_import/src/wasm_declarations.rs | 264+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
26 files changed, 3533 insertions(+), 324 deletions(-)

diff --git a/crates/event_bindings/Cargo.toml b/crates/event_bindings/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "radroots_event_bindings" +description = "Generated bindings for Radroots event contracts" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true +publish = false + +[dependencies] +dto_bindgen_backend_ts = { workspace = true } +radroots_event = { workspace = true } diff --git a/crates/event_bindings/src/lib.rs b/crates/event_bindings/src/lib.rs @@ -0,0 +1,24 @@ +pub use radroots_event as upstream; + +mod model; + +pub use model::{constants_module, kinds_module}; + +#[cfg(test)] +mod tests { + use radroots_event::{kinds, listing::RADROOTS_LISTING_PRODUCT_TAG_KEYS}; + + use super::{constants_module, kinds_module}; + + #[test] + fn preserves_event_constant_exports() { + let constants = constants_module().render_source(); + let kinds_ts = kinds_module().render_source(); + assert!(constants.contains("RADROOTS_LISTING_PRODUCT_TAG_KEYS")); + assert!(constants.contains(RADROOTS_LISTING_PRODUCT_TAG_KEYS[0])); + assert!(kinds_ts.contains("KIND_LISTING")); + assert!(kinds_ts.contains(&kinds::KIND_LISTING.to_string())); + assert!(kinds_ts.contains("KIND_ORDER_REQUEST")); + assert!(kinds_ts.contains(&kinds::KIND_ORDER_REQUEST.to_string())); + } +} diff --git a/crates/event_bindings/src/model.rs b/crates/event_bindings/src/model.rs @@ -0,0 +1,192 @@ +use dto_bindgen_backend_ts::{ + TypeScriptDeclaration, TypeScriptImport, TypeScriptModule, TypeScriptType, TypeScriptValue, +}; +use radroots_event::{kinds, listing::RADROOTS_LISTING_PRODUCT_TAG_KEYS}; + +pub fn constants_module() -> TypeScriptModule { + TypeScriptModule::new("src/generated/constants.ts") + .with_import(TypeScriptImport::type_only( + ["RadrootsListingProductTagKeys"], + "./types.js", + )) + .with_declaration(TypeScriptDeclaration::constant( + "RADROOTS_LISTING_PRODUCT_TAG_KEYS", + Some(TypeScriptType::named("RadrootsListingProductTagKeys")), + TypeScriptValue::array( + RADROOTS_LISTING_PRODUCT_TAG_KEYS + .iter() + .map(|value| TypeScriptValue::string(*value)) + .collect::<Vec<_>>(), + ), + )) +} + +pub fn kinds_module() -> TypeScriptModule { + EVENT_KIND_EXPORTS.iter().fold( + TypeScriptModule::new("src/generated/kinds.ts"), + |module, (name, value)| { + module.with_declaration(TypeScriptDeclaration::constant( + *name, + None, + TypeScriptValue::number(i64::from(*value)), + )) + }, + ) +} + +const EVENT_KIND_EXPORTS: &[(&str, u32)] = &[ + ("KIND_PROFILE", kinds::KIND_PROFILE), + ("KIND_POST", kinds::KIND_POST), + ("KIND_FOLLOW", kinds::KIND_FOLLOW), + ("KIND_REACTION", kinds::KIND_REACTION), + ("KIND_SEAL", kinds::KIND_SEAL), + ("KIND_MESSAGE", kinds::KIND_MESSAGE), + ("KIND_MESSAGE_FILE", kinds::KIND_MESSAGE_FILE), + ("KIND_GIFT_WRAP", kinds::KIND_GIFT_WRAP), + ("KIND_COMMENT", kinds::KIND_COMMENT), + ("KIND_GEOCHAT", kinds::KIND_GEOCHAT), + ("KIND_WIKI_MERGE_REQUEST", kinds::KIND_WIKI_MERGE_REQUEST), + ("KIND_WIKI_ARTICLE", kinds::KIND_WIKI_ARTICLE), + ("KIND_WIKI_REDIRECT", kinds::KIND_WIKI_REDIRECT), + ("KIND_LIST_MUTE", kinds::KIND_LIST_MUTE), + ("KIND_LIST_PINNED_NOTES", kinds::KIND_LIST_PINNED_NOTES), + ( + "KIND_LIST_READ_WRITE_RELAYS", + kinds::KIND_LIST_READ_WRITE_RELAYS, + ), + ("KIND_LIST_BOOKMARKS", kinds::KIND_LIST_BOOKMARKS), + ("KIND_LIST_COMMUNITIES", kinds::KIND_LIST_COMMUNITIES), + ("KIND_LIST_PUBLIC_CHATS", kinds::KIND_LIST_PUBLIC_CHATS), + ("KIND_LIST_BLOCKED_RELAYS", kinds::KIND_LIST_BLOCKED_RELAYS), + ("KIND_LIST_SEARCH_RELAYS", kinds::KIND_LIST_SEARCH_RELAYS), + ("KIND_LIST_SIMPLE_GROUPS", kinds::KIND_LIST_SIMPLE_GROUPS), + ("KIND_LIST_RELAY_FEEDS", kinds::KIND_LIST_RELAY_FEEDS), + ("KIND_LIST_INTERESTS", kinds::KIND_LIST_INTERESTS), + ("KIND_LIST_MEDIA_FOLLOWS", kinds::KIND_LIST_MEDIA_FOLLOWS), + ("KIND_LIST_EMOJIS", kinds::KIND_LIST_EMOJIS), + ("KIND_LIST_DM_RELAYS", kinds::KIND_LIST_DM_RELAYS), + ( + "KIND_LIST_GOOD_WIKI_AUTHORS", + kinds::KIND_LIST_GOOD_WIKI_AUTHORS, + ), + ( + "KIND_LIST_GOOD_WIKI_RELAYS", + kinds::KIND_LIST_GOOD_WIKI_RELAYS, + ), + ("KIND_LIST_SET_FOLLOW", kinds::KIND_LIST_SET_FOLLOW), + ("KIND_LIST_SET_GENERIC", kinds::KIND_LIST_SET_GENERIC), + ("KIND_LIST_SET_RELAY", kinds::KIND_LIST_SET_RELAY), + ("KIND_LIST_SET_BOOKMARK", kinds::KIND_LIST_SET_BOOKMARK), + ("KIND_LIST_SET_CURATION", kinds::KIND_LIST_SET_CURATION), + ("KIND_LIST_SET_VIDEO", kinds::KIND_LIST_SET_VIDEO), + ("KIND_LIST_SET_PICTURE", kinds::KIND_LIST_SET_PICTURE), + ("KIND_LIST_SET_KIND_MUTE", kinds::KIND_LIST_SET_KIND_MUTE), + ("KIND_LIST_SET_INTEREST", kinds::KIND_LIST_SET_INTEREST), + ("KIND_LIST_SET_EMOJI", kinds::KIND_LIST_SET_EMOJI), + ( + "KIND_LIST_SET_RELEASE_ARTIFACT", + kinds::KIND_LIST_SET_RELEASE_ARTIFACT, + ), + ( + "KIND_LIST_SET_APP_CURATION", + kinds::KIND_LIST_SET_APP_CURATION, + ), + ("KIND_LIST_SET_CALENDAR", kinds::KIND_LIST_SET_CALENDAR), + ( + "KIND_LIST_SET_STARTER_PACK", + kinds::KIND_LIST_SET_STARTER_PACK, + ), + ( + "KIND_LIST_SET_MEDIA_STARTER_PACK", + kinds::KIND_LIST_SET_MEDIA_STARTER_PACK, + ), + ("KIND_FARM", kinds::KIND_FARM), + ("KIND_PLOT", kinds::KIND_PLOT), + ("KIND_COOP", kinds::KIND_COOP), + ("KIND_DOCUMENT", kinds::KIND_DOCUMENT), + ("KIND_RESOURCE_AREA", kinds::KIND_RESOURCE_AREA), + ( + "KIND_RESOURCE_HARVEST_CAP", + kinds::KIND_RESOURCE_HARVEST_CAP, + ), + ("KIND_ACCOUNT_CLAIM", kinds::KIND_ACCOUNT_CLAIM), + ("KIND_APP_DATA", kinds::KIND_APP_DATA), + ("KIND_LISTING", kinds::KIND_LISTING), + ("KIND_APPLICATION_HANDLER", kinds::KIND_APPLICATION_HANDLER), + ( + "KIND_TRADE_LISTING_VALIDATION_REQUEST", + kinds::KIND_TRADE_LISTING_VALIDATION_REQUEST, + ), + ( + "KIND_TRADE_LISTING_VALIDATION_RESULT", + kinds::KIND_TRADE_LISTING_VALIDATION_RESULT, + ), + ( + "KIND_TRADE_TRANSITION_PROOF_REQUEST", + kinds::KIND_TRADE_TRANSITION_PROOF_REQUEST, + ), + ( + "KIND_TRADE_TRANSITION_PROOF_RESULT", + kinds::KIND_TRADE_TRANSITION_PROOF_RESULT, + ), + ("KIND_ORDER_REQUEST", kinds::KIND_ORDER_REQUEST), + ("KIND_ORDER_DECISION", kinds::KIND_ORDER_DECISION), + ( + "KIND_ORDER_REVISION_PROPOSAL", + kinds::KIND_ORDER_REVISION_PROPOSAL, + ), + ( + "KIND_ORDER_REVISION_DECISION", + kinds::KIND_ORDER_REVISION_DECISION, + ), + ("KIND_ORDER_CANCELLATION", kinds::KIND_ORDER_CANCELLATION), + ("KIND_TRADE_QUESTION", kinds::KIND_TRADE_QUESTION), + ("KIND_TRADE_ANSWER", kinds::KIND_TRADE_ANSWER), + ( + "KIND_TRADE_DISCOUNT_REQUEST", + kinds::KIND_TRADE_DISCOUNT_REQUEST, + ), + ( + "KIND_TRADE_DISCOUNT_OFFER", + kinds::KIND_TRADE_DISCOUNT_OFFER, + ), + ( + "KIND_TRADE_DISCOUNT_ACCEPT", + kinds::KIND_TRADE_DISCOUNT_ACCEPT, + ), + ( + "KIND_TRADE_FORBIDDEN_3431", + kinds::KIND_TRADE_FORBIDDEN_3431, + ), + ( + "KIND_TRADE_FULFILLMENT_UPDATE", + kinds::KIND_TRADE_FULFILLMENT_UPDATE, + ), + ("KIND_TRADE_RECEIPT", kinds::KIND_TRADE_RECEIPT), + ( + "KIND_TRADE_VALIDATION_RECEIPT", + kinds::KIND_TRADE_VALIDATION_RECEIPT, + ), + ("KIND_KNOWLEDGE_CLAIM", kinds::KIND_KNOWLEDGE_CLAIM), + ("KIND_KNOWLEDGE_RELATION", kinds::KIND_KNOWLEDGE_RELATION), + ("KIND_KNOWLEDGE_REVIEW", kinds::KIND_KNOWLEDGE_REVIEW), + ( + "KIND_KNOWLEDGE_FIELD_REPORT", + kinds::KIND_KNOWLEDGE_FIELD_REPORT, + ), + ( + "KIND_KNOWLEDGE_CHANGE_PROPOSAL", + kinds::KIND_KNOWLEDGE_CHANGE_PROPOSAL, + ), + ( + "KIND_CONTRIBUTION_ATTESTATION", + kinds::KIND_CONTRIBUTION_ATTESTATION, + ), + ("KIND_KNOWLEDGE_SOURCE", kinds::KIND_KNOWLEDGE_SOURCE), + ("KIND_EVIDENCE_BOUNTY", kinds::KIND_EVIDENCE_BOUNTY), + ("KIND_JOB_REQUEST_MIN", kinds::KIND_JOB_REQUEST_MIN), + ("KIND_JOB_REQUEST_MAX", kinds::KIND_JOB_REQUEST_MAX), + ("KIND_JOB_RESULT_MIN", kinds::KIND_JOB_RESULT_MIN), + ("KIND_JOB_RESULT_MAX", kinds::KIND_JOB_RESULT_MAX), + ("KIND_JOB_FEEDBACK", kinds::KIND_JOB_FEEDBACK), +]; diff --git a/crates/event_codec_wasm/Cargo.toml b/crates/event_codec_wasm/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "radroots_event_codec_wasm" +publish = false +version = "0.1.0-alpha.2" +edition.workspace = true +authors = ["Tyson Lupul <tyson@radroots.org>"] +rust-version.workspace = true +license.workspace = true +description = "WASM boundary for Radroots event codecs" +repository.workspace = true +homepage.workspace = true +readme = "README" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +radroots_event = { workspace = true, default-features = false, features = [ + "std", + "serde", + "knowledge-nip54", +] } +radroots_event_codec = { workspace = true, default-features = false, features = [ + "std", + "serde_json", + "nostr", + "knowledge-nip54", + "contract-manifest", +] } +serde = { workspace = true } +serde_json = { workspace = true } +wasm-bindgen = { workspace = true } + +[dev-dependencies] +nostr = { workspace = true } +radroots_core = { workspace = true, default-features = false, features = [ + "std", +] } diff --git a/crates/event_codec_wasm/README b/crates/event_codec_wasm/README @@ -0,0 +1,24 @@ +# radroots_event_codec_wasm + +This is the README for `radroots_event_codec_wasm`, which provides WebAssembly +bindings for `radroots_event_codec` in the `radroots` core libraries. + +## Overview + + * wasm-bindgen entry points for event content and tag encoding and decoding; + * specialized tag helpers for farm, list, job, message, plot, and reaction + event families; + * JSON and `JsValue` boundaries built around `serde-wasm-bindgen` and base64 + helpers; + * built as `cdylib` and `rlib` artifacts for wasm consumers. + +## Copyright + +Except as otherwise noted, all files in the `radroots_event_codec_wasm` +distribution are + + Copyright (c) 2026 Tyson Lupul + +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see LICENSE included in the `radroots_event_codec_wasm` +distribution. diff --git a/crates/event_codec_wasm/src/lib.rs b/crates/event_codec_wasm/src/lib.rs @@ -0,0 +1,1732 @@ +#![forbid(unsafe_code)] + +use radroots_event::article::RadrootsArticle; +use radroots_event::calendar::{ + RadrootsCalendar, RadrootsCalendarDateEvent, RadrootsCalendarEventRsvp, + RadrootsCalendarTimeEvent, +}; +use radroots_event::comment::RadrootsComment; +use radroots_event::coop::RadrootsCoop; +use radroots_event::document::RadrootsDocument; +use radroots_event::farm::RadrootsFarm; +use radroots_event::farm_crdt::RadrootsFarmCrdtChange; +use radroots_event::farm_file::RadrootsFarmFileMetadata; +use radroots_event::farm_workspace::RadrootsFarmWorkspaceManifest; +use radroots_event::file_metadata::RadrootsFileMetadata; +use radroots_event::follow::RadrootsFollow; +use radroots_event::gift_wrap::RadrootsGiftWrap; +use radroots_event::group::{ + RadrootsGroupAdmins, RadrootsGroupCreateGroup, RadrootsGroupCreateInvite, + RadrootsGroupDeleteEvent, RadrootsGroupDeleteGroup, RadrootsGroupEditMetadata, + RadrootsGroupJoinRequest, RadrootsGroupLeaveRequest, RadrootsGroupMembers, + RadrootsGroupMetadata, RadrootsGroupPutUser, RadrootsGroupRemoveUser, RadrootsGroupRoles, +}; +use radroots_event::http_auth::RadrootsHttpAuth; +use radroots_event::job_feedback::RadrootsJobFeedback; +use radroots_event::job_request::RadrootsJobRequest; +use radroots_event::job_result::RadrootsJobResult; +use radroots_event::knowledge::{ + RadrootsKnowledgeClaim, RadrootsKnowledgeFieldReport, RadrootsKnowledgeRelation, + RadrootsKnowledgeReview, RadrootsKnowledgeSource, RadrootsWikiArticle, + RadrootsWikiMergeRequest, RadrootsWikiRedirect, +}; +use radroots_event::list::RadrootsList; +use radroots_event::list_set::RadrootsListSet; +use radroots_event::listing::RadrootsListing; +use radroots_event::message::RadrootsMessage; +use radroots_event::message_file::RadrootsMessageFile; +use radroots_event::plot::RadrootsPlot; +use radroots_event::post::RadrootsPost; +use radroots_event::reaction::RadrootsReaction; +use radroots_event::relay_auth::RadrootsRelayAuth; +use radroots_event::report::RadrootsReport; +use radroots_event::repost::{RadrootsGenericRepost, RadrootsRepost}; +use radroots_event::seal::RadrootsSeal; +use radroots_event_codec::article::encode::article_build_tags; +use radroots_event_codec::calendar::encode::{ + calendar_collection_build_tags, calendar_date_event_build_tags, calendar_time_event_build_tags, + rsvp_build_tags, +}; +use radroots_event_codec::comment::encode::comment_build_tags; +use radroots_event_codec::coop::encode::coop_build_tags; +use radroots_event_codec::document::encode::document_build_tags; +use radroots_event_codec::farm::encode::farm_build_tags; +use radroots_event_codec::farm_crdt::encode::farm_crdt_change_build_tags_with_author; +use radroots_event_codec::farm_file::encode::farm_file_metadata_build_tags; +use radroots_event_codec::farm_workspace::encode::farm_workspace_build_tags; +use radroots_event_codec::file_metadata::encode::file_metadata_build_tags; +use radroots_event_codec::follow::encode::follow_build_tags; +use radroots_event_codec::gift_wrap::encode::gift_wrap_build_tags; +use radroots_event_codec::group::encode::{ + group_admins_build_tags, group_create_group_build_tags, group_create_invite_build_tags, + group_delete_event_build_tags, group_delete_group_build_tags, group_edit_metadata_build_tags, + group_join_request_build_tags, group_leave_request_build_tags, group_members_build_tags, + group_metadata_build_tags, group_put_user_build_tags, group_remove_user_build_tags, + group_roles_build_tags, +}; +use radroots_event_codec::http_auth::encode::http_auth_build_tags; +use radroots_event_codec::job::feedback::encode::job_feedback_build_tags; +use radroots_event_codec::job::request::encode::job_request_build_tags; +use radroots_event_codec::job::result::encode::job_result_build_tags; +use radroots_event_codec::knowledge::{ + knowledge_claim_build_tags, knowledge_field_report_build_tags, knowledge_relation_build_tags, + knowledge_review_build_tags, knowledge_source_build_tags, wiki_article_build_tags, + wiki_merge_request_build_tags, wiki_redirect_build_tags, +}; +use radroots_event_codec::list::encode::list_build_tags; +use radroots_event_codec::list_set::encode::list_set_build_tags; +use radroots_event_codec::listing::tags::{ + listing_tags as listing_tags_impl, listing_tags_full as listing_tags_full_impl, +}; +use radroots_event_codec::message::encode::message_build_tags; +use radroots_event_codec::message_file::encode::message_file_build_tags; +use radroots_event_codec::plot::encode::plot_build_tags; +use radroots_event_codec::post::encode::post_build_tags; +use radroots_event_codec::reaction::encode::reaction_build_tags; +use radroots_event_codec::relay_auth::encode::relay_auth_build_tags; +use radroots_event_codec::report::encode::report_build_tags; +use radroots_event_codec::repost::encode::{generic_repost_build_tags, repost_build_tags}; +use radroots_event_codec::seal::encode::seal_build_tags; +use radroots_event_codec::verification::{RadrootsDecodeError, RadrootsDecodedEvent}; +use serde::Serialize; +use serde::de::DeserializeOwned; +#[cfg(target_arch = "wasm32")] +use wasm_bindgen::JsValue; +#[cfg(target_arch = "wasm32")] +use wasm_bindgen::prelude::*; + +#[cfg(target_arch = "wasm32")] +type RadrootsJsValue = JsValue; + +#[cfg(not(target_arch = "wasm32"))] +type RadrootsJsValue = String; + +fn err_js<E: ToString>(err: E) -> RadrootsJsValue { + #[cfg(target_arch = "wasm32")] + { + JsValue::from_str(&err.to_string()) + } + #[cfg(not(target_arch = "wasm32"))] + { + err.to_string() + } +} + +fn error_json(code: &str, inner_code: Option<&str>) -> RadrootsJsValue { + let value = serde_json::json!({ + "code": code, + "inner_code": inner_code, + }); + err_js(value) +} + +fn normalized_payload(input: &str) -> &str { + if input.is_empty() { "{}" } else { input } +} + +fn parse_json<T: DeserializeOwned>(input: &str) -> Result<T, RadrootsJsValue> { + serde_json::from_str(normalized_payload(input)).map_err(err_js) +} + +fn tags_to_json(tags: Vec<Vec<String>>) -> Result<String, RadrootsJsValue> { + serde_json::to_string(&tags).map_err(err_js) +} + +fn parse_event_json(input: &str) -> Result<radroots_event::RadrootsEventEnvelope, RadrootsJsValue> { + serde_json::from_str(input).map_err(|_| error_json("invalid_json", Some("event_json"))) +} + +fn build_tags_json<T, E, F>(input: &str, build: F) -> Result<String, RadrootsJsValue> +where + T: DeserializeOwned, + E: ToString, + F: FnOnce(&T) -> Result<Vec<Vec<String>>, E>, +{ + let value = parse_json::<T>(input)?; + let tags = build(&value).map_err(err_js)?; + tags_to_json(tags) +} + +fn build_tags_json_infallible<T, F>(input: &str, build: F) -> Result<String, RadrootsJsValue> +where + T: DeserializeOwned, + F: FnOnce(&T) -> Vec<Vec<String>>, +{ + let value = parse_json::<T>(input)?; + let tags = build(&value); + tags_to_json(tags) +} + +#[derive(Serialize)] +struct DecodedEventJson<'a, T> +where + T: Serialize, +{ + event_type: &'static str, + contract_id: &'static str, + event: &'a radroots_event::RadrootsEventEnvelope, + payload: &'a T, +} + +fn decoded_event_to_json(decoded: RadrootsDecodedEvent) -> Result<String, RadrootsJsValue> { + match decoded { + RadrootsDecodedEvent::WikiArticle(parsed) => { + decoded_payload_to_json("wiki_article", "radroots.wiki.article.v1", &parsed) + } + RadrootsDecodedEvent::WikiRedirect(parsed) => { + decoded_payload_to_json("wiki_redirect", "radroots.wiki.redirect.v1", &parsed) + } + RadrootsDecodedEvent::WikiMergeRequest(parsed) => decoded_payload_to_json( + "wiki_merge_request", + "radroots.wiki.merge_request.v1", + &parsed, + ), + RadrootsDecodedEvent::KnowledgeSource(parsed) => { + decoded_payload_to_json("knowledge_source", "radroots.knowledge.source.v1", &parsed) + } + RadrootsDecodedEvent::KnowledgeClaim(parsed) => { + decoded_payload_to_json("knowledge_claim", "radroots.knowledge.claim.v1", &parsed) + } + RadrootsDecodedEvent::KnowledgeRelation(parsed) => decoded_payload_to_json( + "knowledge_relation", + "radroots.knowledge.relation.v1", + &parsed, + ), + RadrootsDecodedEvent::KnowledgeReview(parsed) => { + decoded_payload_to_json("knowledge_review", "radroots.knowledge.review.v1", &parsed) + } + RadrootsDecodedEvent::KnowledgeFieldReport(parsed) => decoded_payload_to_json( + "knowledge_field_report", + "radroots.knowledge.field_report.v1", + &parsed, + ), + RadrootsDecodedEvent::EvidenceBounty(parsed) => decoded_payload_to_json( + "evidence_bounty", + "radroots.knowledge.evidence_bounty.v1", + &parsed, + ), + RadrootsDecodedEvent::KnowledgeChangeProposal(parsed) => decoded_payload_to_json( + "knowledge_change_proposal", + "radroots.knowledge.change_proposal.v1", + &parsed, + ), + RadrootsDecodedEvent::ContributionAttestation(parsed) => decoded_payload_to_json( + "contribution_attestation", + "radroots.knowledge.contribution_attestation.v1", + &parsed, + ), + } +} + +fn decoded_payload_to_json<T>( + event_type: &'static str, + contract_id: &'static str, + parsed: &radroots_event_codec::parsed::RadrootsParsedEvent<T>, +) -> Result<String, RadrootsJsValue> +where + T: Serialize, +{ + serde_json::to_string(&DecodedEventJson { + event_type, + contract_id, + event: &parsed.event, + payload: &parsed.data.data, + }) + .map_err(err_js) +} + +fn decode_error_json(error: RadrootsDecodeError) -> RadrootsJsValue { + let inner = match &error { + RadrootsDecodeError::Nip01Verification(error) => Some(error.code()), + RadrootsDecodeError::ContractValidation(error) => Some(error.code()), + RadrootsDecodeError::EventParse(error) => Some(error.code()), + RadrootsDecodeError::UnsupportedContract { .. } => None, + }; + error_json(error.code(), inner) +} + +#[derive(serde::Deserialize)] +struct FarmCrdtTagsInput { + change: RadrootsFarmCrdtChange, + author_pubkey: String, +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = listing_tags))] +pub fn listing_tags(listing_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsListing, _, _>(listing_json, listing_tags_impl) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = listing_tags_full))] +pub fn listing_tags_full(listing_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsListing, _, _>(listing_json, listing_tags_full_impl) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = post_tags))] +pub fn post_tags(post_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsPost, _, _>(post_json, post_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = comment_tags))] +pub fn comment_tags(comment_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsComment, _, _>(comment_json, comment_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = article_tags))] +pub fn article_tags(article_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsArticle, _, _>(article_json, article_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = wiki_article_tags))] +pub fn wiki_article_tags(article_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsWikiArticle, _, _>(article_json, wiki_article_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = wiki_redirect_tags))] +pub fn wiki_redirect_tags(redirect_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsWikiRedirect, _, _>(redirect_json, wiki_redirect_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = wiki_merge_request_tags))] +pub fn wiki_merge_request_tags(request_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsWikiMergeRequest, _, _>(request_json, wiki_merge_request_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = knowledge_source_tags))] +pub fn knowledge_source_tags(source_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsKnowledgeSource, _, _>(source_json, knowledge_source_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = knowledge_claim_tags))] +pub fn knowledge_claim_tags(claim_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsKnowledgeClaim, _, _>(claim_json, knowledge_claim_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = knowledge_relation_tags))] +pub fn knowledge_relation_tags(relation_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsKnowledgeRelation, _, _>(relation_json, knowledge_relation_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = knowledge_review_tags))] +pub fn knowledge_review_tags(review_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsKnowledgeReview, _, _>(review_json, knowledge_review_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = knowledge_field_report_tags))] +pub fn knowledge_field_report_tags(report_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsKnowledgeFieldReport, _, _>( + report_json, + knowledge_field_report_build_tags, + ) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = verify_and_decode_event_json))] +pub fn verify_and_decode_event_json(event_json: &str) -> Result<String, RadrootsJsValue> { + let event = parse_event_json(event_json)?; + let decoded = + radroots_event_codec::verify_and_decode_radroots_event(event).map_err(decode_error_json)?; + decoded_event_to_json(decoded) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = contract_manifest_json))] +pub fn contract_manifest_json() -> Result<String, RadrootsJsValue> { + radroots_event_codec::contract_manifest_json().map_err(err_js) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = file_metadata_tags))] +pub fn file_metadata_tags(metadata_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsFileMetadata, _, _>(metadata_json, file_metadata_build_tags) +} + +#[cfg_attr( + target_arch = "wasm32", + wasm_bindgen(js_name = calendar_date_event_tags) +)] +pub fn calendar_date_event_tags(event_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsCalendarDateEvent, _, _>(event_json, calendar_date_event_build_tags) +} + +#[cfg_attr( + target_arch = "wasm32", + wasm_bindgen(js_name = calendar_time_event_tags) +)] +pub fn calendar_time_event_tags(event_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsCalendarTimeEvent, _, _>(event_json, calendar_time_event_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = calendar_tags))] +pub fn calendar_tags(calendar_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsCalendar, _, _>(calendar_json, calendar_collection_build_tags) +} + +#[cfg_attr( + target_arch = "wasm32", + wasm_bindgen(js_name = calendar_event_rsvp_tags) +)] +pub fn calendar_event_rsvp_tags(rsvp_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsCalendarEventRsvp, _, _>(rsvp_json, rsvp_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = repost_tags))] +pub fn repost_tags(repost_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsRepost, _, _>(repost_json, repost_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = generic_repost_tags))] +pub fn generic_repost_tags(repost_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGenericRepost, _, _>(repost_json, generic_repost_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = report_tags))] +pub fn report_tags(report_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsReport, _, _>(report_json, report_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = follow_tags))] +pub fn follow_tags(follow_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsFollow, _, _>(follow_json, follow_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = document_tags))] +pub fn document_tags(document_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsDocument, _, _>(document_json, document_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = coop_tags))] +pub fn coop_tags(coop_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsCoop, _, _>(coop_json, coop_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = farm_tags))] +pub fn farm_tags(farm_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsFarm, _, _>(farm_json, farm_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = list_tags))] +pub fn list_tags(list_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsList, _, _>(list_json, list_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = list_set_tags))] +pub fn list_set_tags(list_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsListSet, _, _>(list_json, list_set_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = plot_tags))] +pub fn plot_tags(plot_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsPlot, _, _>(plot_json, plot_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = job_request_tags))] +pub fn job_request_tags(job_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json_infallible::<RadrootsJobRequest, _>(job_json, job_request_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = job_result_tags))] +pub fn job_result_tags(job_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json_infallible::<RadrootsJobResult, _>(job_json, job_result_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = job_feedback_tags))] +pub fn job_feedback_tags(job_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json_infallible::<RadrootsJobFeedback, _>(job_json, job_feedback_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = reaction_tags))] +pub fn reaction_tags(reaction_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsReaction, _, _>(reaction_json, reaction_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = message_tags))] +pub fn message_tags(message_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsMessage, _, _>(message_json, message_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = message_file_tags))] +pub fn message_file_tags(message_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsMessageFile, _, _>(message_json, message_file_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = seal_tags))] +pub fn seal_tags(seal_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsSeal, _, _>(seal_json, seal_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = gift_wrap_tags))] +pub fn gift_wrap_tags(gift_wrap_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGiftWrap, _, _>(gift_wrap_json, gift_wrap_build_tags) +} + +#[cfg_attr( + target_arch = "wasm32", + wasm_bindgen(js_name = farm_workspace_manifest_tags) +)] +pub fn farm_workspace_manifest_tags(workspace_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsFarmWorkspaceManifest, _, _>( + workspace_json, + farm_workspace_build_tags, + ) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = farm_crdt_change_tags))] +pub fn farm_crdt_change_tags(input_json: &str) -> Result<String, RadrootsJsValue> { + let input = parse_json::<FarmCrdtTagsInput>(input_json)?; + let tags = farm_crdt_change_build_tags_with_author(&input.change, Some(&input.author_pubkey)) + .map_err(err_js)?; + tags_to_json(tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = farm_file_metadata_tags))] +pub fn farm_file_metadata_tags(file_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsFarmFileMetadata, _, _>(file_json, farm_file_metadata_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = relay_auth_tags))] +pub fn relay_auth_tags(auth_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsRelayAuth, _, _>(auth_json, relay_auth_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = http_auth_tags))] +pub fn http_auth_tags(auth_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsHttpAuth, _, _>(auth_json, http_auth_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_put_user_tags))] +pub fn group_put_user_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupPutUser, _, _>(group_json, group_put_user_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_remove_user_tags))] +pub fn group_remove_user_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupRemoveUser, _, _>(group_json, group_remove_user_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_create_group_tags))] +pub fn group_create_group_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupCreateGroup, _, _>(group_json, group_create_group_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_edit_metadata_tags))] +pub fn group_edit_metadata_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupEditMetadata, _, _>(group_json, group_edit_metadata_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_delete_group_tags))] +pub fn group_delete_group_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupDeleteGroup, _, _>(group_json, group_delete_group_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_delete_event_tags))] +pub fn group_delete_event_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupDeleteEvent, _, _>(group_json, group_delete_event_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_create_invite_tags))] +pub fn group_create_invite_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupCreateInvite, _, _>(group_json, group_create_invite_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_join_request_tags))] +pub fn group_join_request_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupJoinRequest, _, _>(group_json, group_join_request_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_leave_request_tags))] +pub fn group_leave_request_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupLeaveRequest, _, _>(group_json, group_leave_request_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_metadata_tags))] +pub fn group_metadata_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupMetadata, _, _>(group_json, group_metadata_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_admins_tags))] +pub fn group_admins_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupAdmins, _, _>(group_json, group_admins_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_members_tags))] +pub fn group_members_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupMembers, _, _>(group_json, group_members_build_tags) +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = group_roles_tags))] +pub fn group_roles_tags(group_json: &str) -> Result<String, RadrootsJsValue> { + build_tags_json::<RadrootsGroupRoles, _, _>(group_json, group_roles_build_tags) +} + +#[cfg(test)] +mod tests { + use super::*; + use radroots_core::{ + RadrootsCoreCurrency, RadrootsCoreDecimal, RadrootsCoreMoney, RadrootsCoreQuantity, + RadrootsCoreQuantityPrice, RadrootsCoreUnit, + }; + use radroots_event::farm::RadrootsFarmRef; + use radroots_event::farm_crdt::{ + RADROOTS_FARM_CRDT_CHANGE_SCHEMA, RadrootsCrdtBackend, RadrootsFarmCrdtDocumentKind, + RadrootsFarmSemanticKind, + }; + use radroots_event::farm_file::{ + RadrootsFarmFileDimensions, RadrootsFarmFileMetadata, RadrootsFarmFileSource, + }; + use radroots_event::farm_workspace::{ + RADROOTS_FARM_WORKSPACE_PROTOCOL_VERSION, RADROOTS_FARM_WORKSPACE_SCHEMA, + RadrootsFarmWorkspaceManifest, RadrootsFarmWorkspaceMediaServer, RadrootsFarmWorkspaceRef, + RadrootsFarmWorkspaceRelay, RadrootsFarmWorkspaceRelayMode, + }; + use radroots_event::group::{ + RadrootsGroupAdmins, RadrootsGroupCreateGroup, RadrootsGroupCreateInvite, + RadrootsGroupDeleteEvent, RadrootsGroupDeleteGroup, RadrootsGroupEditMetadata, + RadrootsGroupEditableMetadata, RadrootsGroupJoinRequest, RadrootsGroupLeaveRequest, + RadrootsGroupMembers, RadrootsGroupMetadata, RadrootsGroupPutUser, RadrootsGroupRemoveUser, + RadrootsGroupRole, RadrootsGroupRoles, RadrootsGroupUserRef, + }; + use radroots_event::http_auth::RadrootsHttpAuth; + use radroots_event::job::JobInputType; + use radroots_event::job_request::{RadrootsJobInput, RadrootsJobParam}; + use radroots_event::kinds::{ + KIND_FARM_FILE_METADATA, KIND_FILE_METADATA, KIND_KNOWLEDGE_CLAIM, KIND_KNOWLEDGE_SOURCE, + KIND_WIKI_ARTICLE, + }; + use radroots_event::knowledge::{ + RADROOTS_KNOWLEDGE_CLAIM_SCHEMA, RADROOTS_KNOWLEDGE_FIELD_REPORT_SCHEMA, + RADROOTS_KNOWLEDGE_RELATION_SCHEMA, RADROOTS_KNOWLEDGE_REVIEW_SCHEMA, + RADROOTS_KNOWLEDGE_SCHEMA_VERSION, RADROOTS_KNOWLEDGE_SOURCE_SCHEMA, + RadrootsAddressableRef, RadrootsKnowledgeCitationSpan, RadrootsKnowledgeFieldContext, + RadrootsKnowledgeLocation, RadrootsKnowledgeLocationPrecision, RadrootsKnowledgeNodeRef, + RadrootsKnowledgeObservation, RadrootsKnowledgeObservationValue, + RadrootsKnowledgeReviewScope, RadrootsKnowledgeReviewScore, RadrootsKnowledgeReviewTarget, + RadrootsWikiArticleVersionRef, + }; + use radroots_event::listing::{RadrootsListingBin, RadrootsListingProduct}; + use radroots_event::relay_auth::RadrootsRelayAuth; + use radroots_event::social::{ + RadrootsCalendarDateValue, RadrootsCalendarEventFreeBusy, RadrootsCalendarEventRsvpStatus, + RadrootsCalendarParticipant, RadrootsReportFileTarget, RadrootsReportType, + RadrootsSocialFarmAnchor, RadrootsSocialLocation, RadrootsSocialMediaDimensions, + RadrootsSocialMediaMetadata, RadrootsSocialTarget, + }; + + fn sample_listing() -> RadrootsListing { + let quantity = + RadrootsCoreQuantity::new(RadrootsCoreDecimal::from(1u32), RadrootsCoreUnit::Each); + let price = RadrootsCoreQuantityPrice::new( + RadrootsCoreMoney::new(RadrootsCoreDecimal::from(10u32), RadrootsCoreCurrency::USD), + quantity.clone(), + ); + + RadrootsListing { + d_tag: "AAAAAAAAAAAAAAAAAAAAAg".parse().expect("listing d tag"), + published_at: None, + farm: RadrootsFarmRef { + pubkey: "farm_pubkey".to_string(), + d_tag: "AAAAAAAAAAAAAAAAAAAAAA".to_string(), + }, + product: RadrootsListingProduct { + key: "sku".to_string(), + title: "widget".to_string(), + category: "tools".to_string(), + summary: None, + process: None, + lot: None, + location: None, + profile: None, + year: None, + }, + primary_bin_id: "bin-1".parse().expect("primary bin id"), + bins: vec![RadrootsListingBin { + bin_id: "bin-1".parse().expect("bin id"), + quantity, + price_per_canonical_unit: price, + display_amount: None, + display_unit: None, + display_label: None, + display_price: None, + display_price_unit: None, + }], + resource_area: None, + plot: None, + discounts: None, + inventory_available: None, + availability: None, + delivery_method: None, + location: None, + images: None, + } + } + + fn synthetic_pubkey(seed: char) -> String { + seed.to_string().repeat(64) + } + + fn synthetic_event_id(seed: char) -> String { + seed.to_string().repeat(64) + } + + fn social_farm_anchor() -> RadrootsSocialFarmAnchor { + RadrootsSocialFarmAnchor { + farm: RadrootsFarmRef { + pubkey: synthetic_pubkey('a'), + d_tag: "AAAAAAAAAAAAAAAAAAAAAA".to_string(), + }, + relays: Some(vec!["wss://relay.example.test".to_string()]), + } + } + + fn event_target(kind: u32, seed: char) -> RadrootsSocialTarget { + RadrootsSocialTarget::Event { + id: synthetic_event_id(seed), + author: Some(synthetic_pubkey('b')), + event_kind: Some(kind), + relays: Some(vec!["wss://relay.example.test".to_string()]), + } + } + + fn address_target(kind: u32, d_tag: &str) -> RadrootsSocialTarget { + let author = synthetic_pubkey('c'); + RadrootsSocialTarget::Address { + address: format!("{kind}:{author}:{d_tag}"), + author: Some(author), + event_kind: Some(kind), + relays: Some(vec!["wss://relay2.example.test".to_string()]), + } + } + + fn knowledge_event_ref(seed: char, kind: u32) -> radroots_event::RadrootsEventRef { + radroots_event::RadrootsEventRef { + id: synthetic_event_id(seed), + author: synthetic_pubkey('a'), + kind, + d_tag: None, + relays: Some(vec!["wss://relay.example.test".to_string()]), + } + } + + fn knowledge_address_ref() -> RadrootsAddressableRef { + RadrootsAddressableRef { + kind: KIND_WIKI_ARTICLE, + pubkey: synthetic_pubkey('a'), + d_tag: "soil-health".to_string(), + relays: vec!["wss://relay.example.test".to_string()], + } + } + + fn sample_wiki_article() -> RadrootsWikiArticle { + RadrootsWikiArticle { + d_tag: "soil-health".to_string(), + title: Some("Soil health".to_string()), + content_djot: "# Soil health".to_string(), + summary: Some("Living soil basics".to_string()), + topics: vec!["soil".to_string()], + references: vec![knowledge_event_ref('1', KIND_KNOWLEDGE_SOURCE)], + forked_from: vec![RadrootsWikiArticleVersionRef { + event_id: synthetic_event_id('b'), + address_ref: knowledge_address_ref(), + }], + deferred_to: None, + } + } + + fn sample_wiki_redirect() -> RadrootsWikiRedirect { + RadrootsWikiRedirect { + d_tag: "soil".to_string(), + target: knowledge_address_ref(), + } + } + + fn sample_wiki_merge_request() -> RadrootsWikiMergeRequest { + RadrootsWikiMergeRequest { + target_article: knowledge_address_ref(), + destination_pubkey: synthetic_pubkey('a'), + base_version_event_id: Some(synthetic_event_id('e')), + source_version_event_id: synthetic_event_id('f'), + explanation: Some("Merge synthetic soil article updates".to_string()), + } + } + + fn sample_knowledge_source() -> RadrootsKnowledgeSource { + RadrootsKnowledgeSource { + schema: RADROOTS_KNOWLEDGE_SOURCE_SCHEMA.to_string(), + schema_version: RADROOTS_KNOWLEDGE_SCHEMA_VERSION, + d_tag: "soil-source".to_string(), + title: "Soil Source".to_string(), + source_type: "book".to_string(), + authors: vec!["A. Example".to_string()], + publisher: Some("Radroots Synthetic Press".to_string()), + publication_year: Some(2026), + edition: None, + canonical_url: Some("https://source.example.test/soil-source".to_string()), + artifact_refs: vec![knowledge_event_ref('3', KIND_FILE_METADATA)], + author_asserted_rights: None, + topics: vec!["soil".to_string()], + summary: Some("Synthetic source for wasm coverage".to_string()), + } + } + + fn sample_knowledge_claim() -> RadrootsKnowledgeClaim { + RadrootsKnowledgeClaim { + schema: RADROOTS_KNOWLEDGE_CLAIM_SCHEMA.to_string(), + schema_version: RADROOTS_KNOWLEDGE_SCHEMA_VERSION, + claim_type: "practice_effect".to_string(), + text: "Cover crops improve soil structure.".to_string(), + citation_spans: vec![RadrootsKnowledgeCitationSpan { + source_ref: knowledge_event_ref('4', KIND_KNOWLEDGE_SOURCE), + artifact_ref: None, + page_start: Some(12), + page_end: Some(13), + section_path: vec!["chapter-1".to_string()], + quote_hash: Some(synthetic_event_id('5')), + chunk_id: Some("chunk-1".to_string()), + }], + topics: vec!["cover-crops".to_string()], + applies_to: vec!["local-food".to_string()], + author_asserted_confidence: Some("medium".to_string()), + supersedes: Vec::new(), + } + } + + fn sample_knowledge_node_ref(label: &str) -> RadrootsKnowledgeNodeRef { + RadrootsKnowledgeNodeRef { + node_type: "event".to_string(), + event_ref: Some(knowledge_event_ref('6', KIND_KNOWLEDGE_CLAIM)), + address_ref: None, + external_id: None, + label: Some(label.to_string()), + } + } + + fn sample_knowledge_relation() -> RadrootsKnowledgeRelation { + RadrootsKnowledgeRelation { + schema: RADROOTS_KNOWLEDGE_RELATION_SCHEMA.to_string(), + schema_version: RADROOTS_KNOWLEDGE_SCHEMA_VERSION, + subject: sample_knowledge_node_ref("cover crops"), + predicate: "supports".to_string(), + object: sample_knowledge_node_ref("soil structure"), + support_refs: vec![knowledge_event_ref('7', KIND_KNOWLEDGE_CLAIM)], + author_asserted_confidence: Some("medium".to_string()), + supersedes: Vec::new(), + } + } + + fn sample_knowledge_review() -> RadrootsKnowledgeReview { + RadrootsKnowledgeReview { + schema: RADROOTS_KNOWLEDGE_REVIEW_SCHEMA.to_string(), + schema_version: RADROOTS_KNOWLEDGE_SCHEMA_VERSION, + target: RadrootsKnowledgeReviewTarget { + event_id: synthetic_event_id('8'), + author_pubkey: synthetic_pubkey('a'), + kind: KIND_KNOWLEDGE_CLAIM, + address: None, + relays: vec!["wss://relay.example.test".to_string()], + review_scope: RadrootsKnowledgeReviewScope::SpecificVersion, + }, + reviewer_role: "peer".to_string(), + verdict: "needs_more_evidence".to_string(), + scores: vec![RadrootsKnowledgeReviewScore { + dimension: "evidence".to_string(), + value: "partial".to_string(), + note: None, + }], + notes: Some("Synthetic review".to_string()), + evidence_refs: vec![knowledge_event_ref('9', KIND_KNOWLEDGE_SOURCE)], + } + } + + fn sample_knowledge_field_report() -> RadrootsKnowledgeFieldReport { + RadrootsKnowledgeFieldReport { + schema: RADROOTS_KNOWLEDGE_FIELD_REPORT_SCHEMA.to_string(), + schema_version: RADROOTS_KNOWLEDGE_SCHEMA_VERSION, + report_type: "observation".to_string(), + title: "Field observation".to_string(), + summary: Some("Observed cover crop residue.".to_string()), + context: RadrootsKnowledgeFieldContext { + location_precision: RadrootsKnowledgeLocationPrecision::CoarseGeohash, + public_location: Some(RadrootsKnowledgeLocation { + label: Some("watershed".to_string()), + region: Some("synthetic-region".to_string()), + locality: None, + geohash: Some("c23".to_string()), + }), + private_location_ref: None, + topics: vec!["field".to_string()], + context_tags: vec!["observation".to_string()], + }, + observations: vec![RadrootsKnowledgeObservation { + observation_type: "residue".to_string(), + text: "Residue was visible across beds.".to_string(), + observed_at: Some("2026-07-05".to_string()), + values: vec![RadrootsKnowledgeObservationValue { + key: "coverage".to_string(), + value: "medium".to_string(), + unit: None, + }], + }], + artifact_refs: vec![knowledge_event_ref('c', KIND_FILE_METADATA)], + related_refs: vec![knowledge_event_ref('d', KIND_KNOWLEDGE_CLAIM)], + limitations: vec!["single observer".to_string()], + } + } + + fn signed_claim_event_json() -> String { + let claim_json = serde_json::to_string(&sample_knowledge_claim()).expect("claim json"); + let tags = serde_json::from_str::<Vec<Vec<String>>>( + &knowledge_claim_tags(&claim_json).expect("claim tags"), + ) + .expect("tags"); + let tags = tags + .into_iter() + .map(nostr::Tag::parse) + .collect::<Result<Vec<_>, _>>() + .expect("parsed tags"); + let keys = + nostr::Keys::parse("0101010101010101010101010101010101010101010101010101010101010101") + .expect("keys"); + let event = + nostr::EventBuilder::new(nostr::Kind::Custom(KIND_KNOWLEDGE_CLAIM as u16), claim_json) + .tags(tags) + .custom_created_at(nostr::Timestamp::from_secs(1_800_000_000)) + .sign_with_keys(&keys) + .expect("signed event"); + serde_json::to_string(&radroots_event::RadrootsEventEnvelope { + id: event.id.to_hex(), + author: event.pubkey.to_hex(), + created_at: event.created_at.as_secs() as u32, + kind: u32::from(event.kind.as_u16()), + tags: event + .tags + .as_slice() + .iter() + .map(|tag| tag.as_slice().to_vec()) + .collect(), + content: event.content, + sig: event.sig.to_string(), + }) + .expect("event json") + } + + fn social_location() -> RadrootsSocialLocation { + RadrootsSocialLocation { + name: Some("field edge".to_string()), + geohash: Some("c23nb62w20st".to_string()), + } + } + + fn sample_post() -> RadrootsPost { + RadrootsPost { + content: "field update".to_string(), + farm: Some(social_farm_anchor()), + address_refs: Some(vec![address_target(30023, "AAAAAAAAAAAAAAAAAAAAAQ")]), + location: Some(social_location()), + topics: Some(vec!["soil".to_string(), "market".to_string()]), + quote_refs: Some(vec![event_target(30023, 'd')]), + media: Some(vec![RadrootsSocialMediaMetadata { + url: Some("https://media.example.test/field.jpg".to_string()), + mime_type: Some("image/jpeg".to_string()), + sha256: Some( + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(), + ), + original_sha256: None, + size: Some(4096), + dimensions: Some(RadrootsSocialMediaDimensions { + width: 1200, + height: 800, + }), + blurhash: None, + thumbnails: None, + image: None, + summary: Some("field photo".to_string()), + alt: Some("rows after harvest".to_string()), + fallback: None, + magnet: Some("magnet:?xt=urn:btih:abc".to_string()), + content_hashes: Some(vec!["sha256:field".to_string()]), + services: Some(vec!["https://media.example.test".to_string()]), + imeta: None, + }]), + } + } + + fn sample_article() -> RadrootsArticle { + RadrootsArticle { + d_tag: "AAAAAAAAAAAAAAAAAAAAAg".to_string(), + title: "soil notes".to_string(), + content: "# soil notes".to_string(), + summary: Some("cover crop observations".to_string()), + image: Some("https://media.example.test/article.jpg".to_string()), + published_at: Some(1_780_000_000), + farm: Some(social_farm_anchor()), + location: Some(social_location()), + topics: Some(vec!["soil".to_string(), "cover-crops".to_string()]), + } + } + + fn sample_public_file_metadata() -> RadrootsFileMetadata { + RadrootsFileMetadata { + url: "https://media.example.test/public.jpg".to_string(), + mime_type: "image/jpeg".to_string(), + sha256: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(), + original_sha256: Some( + "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789".to_string(), + ), + size: Some(4096), + dimensions: Some(RadrootsSocialMediaDimensions { + width: 1200, + height: 800, + }), + blurhash: None, + thumbnails: None, + summary: Some("public field photo".to_string()), + alt: Some("rows after harvest".to_string()), + fallback: Some("https://media.example.test/fallback.jpg".to_string()), + magnet: Some("magnet:?xt=urn:btih:abc".to_string()), + content_hashes: Some(vec!["sha256:field".to_string()]), + services: Some(vec!["https://media.example.test".to_string()]), + content: Some("caption".to_string()), + } + } + + fn sample_calendar_date_event() -> RadrootsCalendarDateEvent { + RadrootsCalendarDateEvent { + d_tag: "AAAAAAAAAAAAAAAAAAAAAw".to_string(), + title: "market day".to_string(), + start: "2026-06-20".to_string(), + description: Some("Farm stand pickup window.".to_string()), + end: Some("2026-06-21".to_string()), + days: Some(vec![RadrootsCalendarDateValue { + value: "2026-06-20".to_string(), + }]), + location: Some(social_location()), + summary: Some("weekly pickup".to_string()), + image: None, + participants: Some(vec![RadrootsCalendarParticipant { + pubkey: synthetic_pubkey('e'), + relay: Some("wss://relay.example.test".to_string()), + role: Some("host".to_string()), + }]), + } + } + + fn sample_calendar_time_event() -> RadrootsCalendarTimeEvent { + RadrootsCalendarTimeEvent { + d_tag: "AAAAAAAAAAAAAAAAAAAA-A".to_string(), + title: "wash pack shift".to_string(), + start: 1_781_895_600, + dates: vec![RadrootsCalendarDateValue { + value: "2026-06-20".to_string(), + }], + description: Some("Prepare CSA bins before pickup.".to_string()), + end: Some(1_781_899_200), + start_tzid: Some("America/Vancouver".to_string()), + end_tzid: Some("America/Vancouver".to_string()), + location: Some(social_location()), + summary: Some("field crew".to_string()), + image: None, + participants: None, + } + } + + fn sample_calendar() -> RadrootsCalendar { + RadrootsCalendar { + d_tag: "AAAAAAAAAAAAAAAAAAAA_A".to_string(), + title: "farm calendar".to_string(), + events: vec![address_target(31923, "AAAAAAAAAAAAAAAAAAAA-A")], + description: Some("Shared schedule for farm operations.".to_string()), + summary: Some("field schedule".to_string()), + image: None, + } + } + + fn sample_calendar_rsvp() -> RadrootsCalendarEventRsvp { + RadrootsCalendarEventRsvp { + d_tag: "AAAAAAAAAAAAAAAAAAAAAQ".to_string(), + event: address_target(31923, "AAAAAAAAAAAAAAAAAAAA-A"), + event_id: Some(synthetic_event_id('f')), + status: RadrootsCalendarEventRsvpStatus::Tentative, + free_busy: Some(RadrootsCalendarEventFreeBusy::Busy), + note: Some("depends on harvest".to_string()), + participants: None, + } + } + + fn sample_comment() -> RadrootsComment { + RadrootsComment { + root: event_target(30023, 'a'), + parent: address_target(30023, "AAAAAAAAAAAAAAAAAAAAAg"), + content: "great notes".to_string(), + } + } + + fn sample_reaction() -> RadrootsReaction { + RadrootsReaction { + target: address_target(30023, "AAAAAAAAAAAAAAAAAAAAAg"), + content: String::new(), + } + } + + fn sample_repost() -> RadrootsRepost { + RadrootsRepost { + target: event_target(1, 'b'), + content: Some("field update".to_string()), + } + } + + fn sample_generic_repost() -> RadrootsGenericRepost { + RadrootsGenericRepost { + target: address_target(30023, "AAAAAAAAAAAAAAAAAAAAAg"), + target_kind: 30023, + content: Some("article share".to_string()), + } + } + + fn sample_report() -> RadrootsReport { + RadrootsReport { + reported_pubkey: synthetic_pubkey('b'), + report_type: RadrootsReportType::Spam, + event: Some(event_target(1, 'c')), + file: Some(RadrootsReportFileTarget { + sha256: Some( + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(), + ), + url: Some("https://media.example.test/bad.jpg".to_string()), + magnet: None, + }), + content: Some("spam report".to_string()), + } + } + + fn sample_job_request() -> RadrootsJobRequest { + RadrootsJobRequest { + kind: 5100, + inputs: vec![RadrootsJobInput { + data: "alpha".to_string(), + input_type: JobInputType::Text, + relay: None, + marker: None, + }], + output: None, + params: vec![RadrootsJobParam { + key: "mode".to_string(), + value: "fast".to_string(), + }], + bid_sat: Some(42), + relays: vec!["wss://relay.example.com".to_string()], + providers: vec!["provider-a".to_string()], + topics: vec!["topic-a".to_string()], + encrypted: false, + } + } + + fn sample_workspace_manifest() -> RadrootsFarmWorkspaceManifest { + RadrootsFarmWorkspaceManifest { + d_tag: "AAAAAAAAAAAAAAAAAAAAAA".to_string(), + schema: RADROOTS_FARM_WORKSPACE_SCHEMA.to_string(), + farm_group_id: "field-group".to_string(), + name: "Small Regen Farm".to_string(), + owner_pubkey: "workspace_owner_pubkey".to_string(), + farm: Some(RadrootsFarmRef { + pubkey: "farm_pubkey".to_string(), + d_tag: "AAAAAAAAAAAAAAAAAAAAAQ".to_string(), + }), + relays: vec![RadrootsFarmWorkspaceRelay { + url: "wss://relay.example.invalid/farm/field-group".to_string(), + mode: RadrootsFarmWorkspaceRelayMode::ReadWrite, + }], + media_servers: vec![RadrootsFarmWorkspaceMediaServer { + url: "https://media.example.invalid/farm/field-group".to_string(), + service: "RadrootsPrivateMedia".to_string(), + }], + supported_kinds: vec![78, 30078, KIND_FARM_FILE_METADATA], + protocol_version: RADROOTS_FARM_WORKSPACE_PROTOCOL_VERSION.to_string(), + created_at_ms: 1_780_000_000_000, + updated_at_ms: None, + } + } + + fn sample_crdt_change() -> RadrootsFarmCrdtChange { + RadrootsFarmCrdtChange { + schema: RADROOTS_FARM_CRDT_CHANGE_SCHEMA.to_string(), + workspace: RadrootsFarmWorkspaceRef { + pubkey: "workspace_pubkey".to_string(), + d_tag: "AAAAAAAAAAAAAAAAAAAAAA".to_string(), + }, + farm_group_id: "field-group".to_string(), + document_id: "AAAAAAAAAAAAAAAAAAAAAg".to_string(), + document_kind: RadrootsFarmCrdtDocumentKind::FarmTask, + crdt_backend: RadrootsCrdtBackend::Automerge, + crdt_backend_version: Some("0.x".to_string()), + actor_id: "actor_abc".to_string(), + change_hash: "crdt_hash_abc".to_string(), + dependencies: Vec::new(), + encoded_change: "abc-DEF_012".to_string(), + semantic_kind: RadrootsFarmSemanticKind::FarmTaskCreate, + business_time_ms: 1_780_000_000_000, + author_member_id: Some("member_abc".to_string()), + app_version: Some("0.1.0".to_string()), + } + } + + fn sample_file_metadata() -> RadrootsFarmFileMetadata { + RadrootsFarmFileMetadata { + d_tag: "AAAAAAAAAAAAAAAAAAAAAQ".to_string(), + workspace: RadrootsFarmWorkspaceRef { + pubkey: "workspace_pubkey".to_string(), + d_tag: "AAAAAAAAAAAAAAAAAAAAAA".to_string(), + }, + farm_group_id: "field-group".to_string(), + owner_document_id: "AAAAAAAAAAAAAAAAAAAAAg".to_string(), + owner_document_kind: RadrootsFarmCrdtDocumentKind::FarmTask, + caption: Some("Tomatoes harvested from Patch Y.".to_string()), + url: "https://media.example.invalid/blob/sha256".to_string(), + mime_type: "image/jpeg".to_string(), + sha256: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(), + original_sha256: None, + size_bytes: Some(123_456), + dimensions: Some(RadrootsFarmFileDimensions { w: 1600, h: 1200 }), + blurhash: None, + thumb: Some(RadrootsFarmFileSource { + url: "https://media.example.invalid/thumb/sha256".to_string(), + mime_type: Some("image/jpeg".to_string()), + dimensions: Some(RadrootsFarmFileDimensions { w: 320, h: 240 }), + }), + image: None, + alt: Some("Harvested tomatoes in a crate".to_string()), + fallbacks: Vec::new(), + } + } + + fn sample_group_metadata() -> RadrootsGroupEditableMetadata { + RadrootsGroupEditableMetadata { + name: Some("Small Regen Farm".to_string()), + about: Some("Field app group".to_string()), + picture: Some("https://media.example.invalid/group.png".to_string()), + is_private: false, + is_restricted: true, + is_closed: false, + is_hidden: false, + supported_kinds: Some(vec![78, 30078, KIND_FARM_FILE_METADATA]), + } + } + + fn sample_group_user(role: &str) -> RadrootsGroupUserRef { + RadrootsGroupUserRef { + pubkey: format!("{role}_pubkey"), + roles: vec![role.to_string()], + } + } + + fn sample_group_role() -> RadrootsGroupRole { + RadrootsGroupRole { + name: "member".to_string(), + description: Some("can read and write group events".to_string()), + permissions: vec!["read".to_string(), "write".to_string()], + } + } + + fn assert_tags_json(value: Result<String, RadrootsJsValue>) { + let tags = tags_json(value); + assert!(!tags.is_empty()); + } + + fn tags_json(value: Result<String, RadrootsJsValue>) -> Vec<Vec<String>> { + let json = value.expect("tags json"); + serde_json::from_str(&json).expect("tags") + } + + fn has_tag(tags: &[Vec<String>], key: &str, value: &str) -> bool { + tags.iter().any(|tag| { + tag.first().map(|entry| entry.as_str()) == Some(key) + && tag.get(1).map(|entry| entry.as_str()) == Some(value) + }) + } + + fn has_exact_tag(tags: &[Vec<String>], expected: &[&str]) -> bool { + tags.iter().any(|tag| { + tag.iter() + .map(|entry| entry.as_str()) + .eq(expected.iter().copied()) + }) + } + + #[test] + fn bindings_reject_invalid_json() { + let bindings: [fn(&str) -> Result<String, RadrootsJsValue>; 46] = [ + listing_tags, + listing_tags_full, + post_tags, + comment_tags, + article_tags, + file_metadata_tags, + calendar_date_event_tags, + calendar_time_event_tags, + calendar_tags, + calendar_event_rsvp_tags, + repost_tags, + generic_repost_tags, + report_tags, + follow_tags, + document_tags, + coop_tags, + farm_tags, + list_tags, + list_set_tags, + plot_tags, + job_request_tags, + job_result_tags, + job_feedback_tags, + reaction_tags, + message_tags, + message_file_tags, + seal_tags, + gift_wrap_tags, + farm_workspace_manifest_tags, + farm_crdt_change_tags, + farm_file_metadata_tags, + relay_auth_tags, + http_auth_tags, + group_put_user_tags, + group_remove_user_tags, + group_create_group_tags, + group_edit_metadata_tags, + group_delete_group_tags, + group_delete_event_tags, + group_create_invite_tags, + group_join_request_tags, + group_leave_request_tags, + group_metadata_tags, + group_admins_tags, + group_members_tags, + group_roles_tags, + ]; + + for binding in bindings { + assert!(binding("{").is_err()); + } + assert!(listing_tags("").is_err()); + } + + #[test] + fn bindings_encode_to_json_when_input_is_valid() { + let listing_json = serde_json::to_string(&sample_listing()).expect("listing json"); + let listing_tags_json = listing_tags(&listing_json).expect("listing tags"); + let listing_tags: Vec<Vec<String>> = + serde_json::from_str(&listing_tags_json).expect("listing tags json"); + assert!(!listing_tags.is_empty()); + + let request_json = serde_json::to_string(&sample_job_request()).expect("request json"); + let request_tags_json = job_request_tags(&request_json).expect("request tags"); + let request_tags: Vec<Vec<String>> = + serde_json::from_str(&request_tags_json).expect("request tags json"); + assert!(!request_tags.is_empty()); + } + + #[test] + fn social_bindings_encode_to_json_when_input_is_valid() { + assert_tags_json(post_tags( + &serde_json::to_string(&sample_post()).expect("post json"), + )); + assert_tags_json(comment_tags( + &serde_json::to_string(&sample_comment()).expect("comment json"), + )); + assert_tags_json(article_tags( + &serde_json::to_string(&sample_article()).expect("article json"), + )); + assert_tags_json(file_metadata_tags( + &serde_json::to_string(&sample_public_file_metadata()).expect("file json"), + )); + assert_tags_json(calendar_date_event_tags( + &serde_json::to_string(&sample_calendar_date_event()).expect("date json"), + )); + let time_tags = tags_json(calendar_time_event_tags( + &serde_json::to_string(&sample_calendar_time_event()).expect("time json"), + )); + assert!(has_tag(&time_tags, "D", "2026-06-20")); + assert_tags_json(calendar_tags( + &serde_json::to_string(&sample_calendar()).expect("calendar json"), + )); + assert_tags_json(calendar_event_rsvp_tags( + &serde_json::to_string(&sample_calendar_rsvp()).expect("rsvp json"), + )); + assert_tags_json(reaction_tags( + &serde_json::to_string(&sample_reaction()).expect("reaction json"), + )); + assert_tags_json(repost_tags( + &serde_json::to_string(&sample_repost()).expect("repost json"), + )); + assert_tags_json(generic_repost_tags( + &serde_json::to_string(&sample_generic_repost()).expect("generic repost json"), + )); + assert_tags_json(report_tags( + &serde_json::to_string(&sample_report()).expect("report json"), + )); + } + + #[test] + fn social_bindings_surface_builder_errors() { + let mut article = sample_article(); + article.d_tag.clear(); + assert!(article_tags(&serde_json::to_string(&article).expect("article json")).is_err()); + + let mut comment = sample_comment(); + comment.root = event_target(1, 'a'); + assert!(comment_tags(&serde_json::to_string(&comment).expect("comment json")).is_err()); + + let mut reaction = sample_reaction(); + reaction.target = RadrootsSocialTarget::External { + id: "https://example.test/object".to_string(), + external_kind: "web".to_string(), + hint: None, + }; + assert!(reaction_tags(&serde_json::to_string(&reaction).expect("reaction json")).is_err()); + + let mut rsvp = sample_calendar_rsvp(); + rsvp.event = event_target(31923, 'f'); + assert!( + calendar_event_rsvp_tags(&serde_json::to_string(&rsvp).expect("rsvp json")).is_err() + ); + + let mut report = sample_report(); + report.reported_pubkey.clear(); + assert!(report_tags(&serde_json::to_string(&report).expect("report json")).is_err()); + } + + #[test] + fn knowledge_bindings_encode_to_json_when_input_is_valid() { + let article_tags = tags_json(wiki_article_tags( + &serde_json::to_string(&sample_wiki_article()).expect("wiki article json"), + )); + assert!(has_tag(&article_tags, "title", "Soil health")); + let fork_address = format!( + "{}:{}:soil-health", + KIND_WIKI_ARTICLE, + synthetic_pubkey('a') + ); + let fork_event_id = synthetic_event_id('b'); + assert!(has_exact_tag( + &article_tags, + &[ + "a", + fork_address.as_str(), + "wss://relay.example.test", + "fork" + ] + )); + assert!(has_exact_tag( + &article_tags, + &[ + "e", + fork_event_id.as_str(), + "wss://relay.example.test", + "fork" + ] + )); + + let redirect_tags = tags_json(wiki_redirect_tags( + &serde_json::to_string(&sample_wiki_redirect()).expect("wiki redirect json"), + )); + let redirect_address = format!( + "{}:{}:soil-health", + KIND_WIKI_ARTICLE, + synthetic_pubkey('a') + ); + assert!(has_exact_tag( + &redirect_tags, + &["a", redirect_address.as_str(), "wss://relay.example.test"] + )); + + let merge_request = sample_wiki_merge_request(); + let merge_parts = + radroots_event_codec::knowledge::wiki_merge_request_to_wire_parts(&merge_request) + .expect("merge request parts"); + assert_eq!(merge_parts.content, "Merge synthetic soil article updates"); + let merge_tags = tags_json(wiki_merge_request_tags( + &serde_json::to_string(&sample_wiki_merge_request()).expect("merge request json"), + )); + let source_event_id = synthetic_event_id('f'); + assert!(has_exact_tag( + &merge_tags, + &["e", source_event_id.as_str(), "", "source"] + )); + + let source_tags = tags_json(knowledge_source_tags( + &serde_json::to_string(&sample_knowledge_source()).expect("source json"), + )); + assert!(has_tag( + &source_tags, + "contract", + RADROOTS_KNOWLEDGE_SOURCE_SCHEMA + )); + + let claim_tags = tags_json(knowledge_claim_tags( + &serde_json::to_string(&sample_knowledge_claim()).expect("claim json"), + )); + assert!(has_tag( + &claim_tags, + "contract", + RADROOTS_KNOWLEDGE_CLAIM_SCHEMA + )); + + assert_tags_json(knowledge_relation_tags( + &serde_json::to_string(&sample_knowledge_relation()).expect("relation json"), + )); + assert_tags_json(knowledge_review_tags( + &serde_json::to_string(&sample_knowledge_review()).expect("review json"), + )); + assert_tags_json(knowledge_field_report_tags( + &serde_json::to_string(&sample_knowledge_field_report()).expect("field report json"), + )); + } + + #[test] + fn wiki_article_tags_accept_missing_title() { + let mut article = sample_wiki_article(); + article.title = None; + let tags = tags_json(wiki_article_tags( + &serde_json::to_string(&article).expect("wiki article json"), + )); + assert!( + !tags + .iter() + .any(|tag| tag.first().map(String::as_str) == Some("title")) + ); + } + + #[test] + fn knowledge_claim_tags_enforce_citation_rules() { + let mut claim = sample_knowledge_claim(); + claim.citation_spans.clear(); + let error = knowledge_claim_tags( + &serde_json::to_string(&claim).expect("uncited source-backed claim json"), + ) + .expect_err("source-backed claim requires citations"); + assert!(error.contains("citation_spans")); + + assert_tags_json(knowledge_claim_tags( + &serde_json::to_string(&sample_knowledge_claim()).expect("claim json"), + )); + + for claim_type in ["hypothesis", "observation", "question"] { + let mut uncited = sample_knowledge_claim(); + uncited.claim_type = claim_type.to_string(); + uncited.citation_spans.clear(); + assert_tags_json(knowledge_claim_tags( + &serde_json::to_string(&uncited).expect("uncited claim json"), + )); + } + } + + #[test] + fn knowledge_bindings_verify_decode_and_manifest_json() { + let decoded = verify_and_decode_event_json(&signed_claim_event_json()).expect("decoded"); + let decoded: serde_json::Value = serde_json::from_str(&decoded).expect("decoded json"); + assert_eq!(decoded["event_type"], "knowledge_claim"); + assert_eq!(decoded["contract_id"], RADROOTS_KNOWLEDGE_CLAIM_SCHEMA); + assert_eq!( + decoded["payload"]["text"], + "Cover crops improve soil structure." + ); + + let manifest = contract_manifest_json().expect("manifest"); + let manifest: serde_json::Value = serde_json::from_str(&manifest).expect("manifest json"); + assert_eq!(manifest["schema_version"], 2); + assert_eq!(manifest["contract_count"], 11); + let claim_contract = manifest["contracts"] + .as_array() + .expect("contracts") + .iter() + .find(|contract| contract["contract_id"] == RADROOTS_KNOWLEDGE_CLAIM_SCHEMA) + .expect("claim contract"); + assert_eq!(claim_contract["sdk_builder_support"], true); + assert_eq!(claim_contract["sdk_draft_support"], true); + assert_eq!(claim_contract["wasm_tag_builder_support"], true); + assert_eq!(claim_contract["wasm_verified_decode_support"], true); + } + + #[test] + fn knowledge_bindings_verify_decode_errors_are_coded_json() { + let invalid_json = verify_and_decode_event_json("not json").expect_err("invalid json"); + let invalid_json: serde_json::Value = + serde_json::from_str(&invalid_json).expect("error json"); + assert_eq!(invalid_json["code"], "invalid_json"); + assert_eq!(invalid_json["inner_code"], "event_json"); + + let mut event: serde_json::Value = + serde_json::from_str(&signed_claim_event_json()).expect("event json"); + event["sig"] = serde_json::Value::String("0".repeat(128)); + let signature_error = + verify_and_decode_event_json(&event.to_string()).expect_err("signature error"); + let signature_error: serde_json::Value = + serde_json::from_str(&signature_error).expect("signature error json"); + assert_eq!(signature_error["code"], "nip01_verification"); + assert_eq!(signature_error["inner_code"], "signature_invalid"); + } + + #[test] + fn field_bindings_encode_to_json_when_input_is_valid() { + let workspace_json = + serde_json::to_string(&sample_workspace_manifest()).expect("workspace json"); + assert_tags_json(farm_workspace_manifest_tags(&workspace_json)); + + let crdt_json = serde_json::json!({ + "change": sample_crdt_change(), + "author_pubkey": "author_pubkey" + }) + .to_string(); + assert_tags_json(farm_crdt_change_tags(&crdt_json)); + + let file_json = serde_json::to_string(&sample_file_metadata()).expect("file json"); + assert_tags_json(farm_file_metadata_tags(&file_json)); + + let relay_auth_json = serde_json::to_string(&RadrootsRelayAuth { + relay: "wss://relay.example.invalid/farm/field-group".to_string(), + challenge: "relay-provided-challenge".to_string(), + }) + .expect("relay auth json"); + assert_tags_json(relay_auth_tags(&relay_auth_json)); + + let http_auth_json = serde_json::to_string(&RadrootsHttpAuth { + url: "https://media.example.invalid/upload".to_string(), + method: "POST".to_string(), + payload_sha256: Some( + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(), + ), + }) + .expect("http auth json"); + assert_tags_json(http_auth_tags(&http_auth_json)); + } + + #[test] + fn field_bindings_surface_builder_errors() { + let crdt_json = serde_json::json!({ + "change": sample_crdt_change(), + "author_pubkey": " " + }) + .to_string(); + + assert!(farm_crdt_change_tags(&crdt_json).is_err()); + } + + #[test] + fn group_bindings_encode_to_json_when_input_is_valid() { + let metadata = sample_group_metadata(); + assert_tags_json(group_put_user_tags( + &serde_json::to_string(&RadrootsGroupPutUser { + group_id: "field-group".to_string(), + message: Some("add member".to_string()), + pubkey: "member_pubkey".to_string(), + roles: vec!["member".to_string()], + }) + .expect("put user json"), + )); + assert_tags_json(group_remove_user_tags( + &serde_json::to_string(&RadrootsGroupRemoveUser { + group_id: "field-group".to_string(), + message: Some("remove member".to_string()), + pubkey: "member_pubkey".to_string(), + }) + .expect("remove user json"), + )); + assert_tags_json(group_create_group_tags( + &serde_json::to_string(&RadrootsGroupCreateGroup { + group_id: "field-group".to_string(), + message: Some("create group".to_string()), + metadata: metadata.clone(), + }) + .expect("create group json"), + )); + assert_tags_json(group_edit_metadata_tags( + &serde_json::to_string(&RadrootsGroupEditMetadata { + group_id: "field-group".to_string(), + message: Some("edit metadata".to_string()), + metadata: metadata.clone(), + }) + .expect("edit metadata json"), + )); + assert_tags_json(group_delete_group_tags( + &serde_json::to_string(&RadrootsGroupDeleteGroup { + group_id: "field-group".to_string(), + message: Some("delete group".to_string()), + }) + .expect("delete group json"), + )); + assert_tags_json(group_delete_event_tags( + &serde_json::to_string(&RadrootsGroupDeleteEvent { + group_id: "field-group".to_string(), + message: Some("delete event".to_string()), + event_id: "event_id".to_string(), + }) + .expect("delete event json"), + )); + let invite_tags = tags_json(group_create_invite_tags( + &serde_json::to_string(&RadrootsGroupCreateInvite { + group_id: "field-group".to_string(), + message: Some("join the field group".to_string()), + code: "invite-code".to_string(), + }) + .expect("invite json"), + )); + assert!(invite_tags.contains(&vec!["code".to_string(), "invite-code".to_string()])); + assert_tags_json(group_join_request_tags( + &serde_json::to_string(&RadrootsGroupJoinRequest { + group_id: "field-group".to_string(), + message: Some("requesting access".to_string()), + code: Some("invite-code".to_string()), + }) + .expect("join json"), + )); + assert_tags_json(group_leave_request_tags( + &serde_json::to_string(&RadrootsGroupLeaveRequest { + group_id: "field-group".to_string(), + message: Some("leaving".to_string()), + }) + .expect("leave json"), + )); + let metadata_tags = tags_json(group_metadata_tags( + &serde_json::to_string(&RadrootsGroupMetadata { + d_tag: "field-group".to_string(), + metadata, + }) + .expect("metadata json"), + )); + assert!(metadata_tags.contains(&vec!["restricted".to_string()])); + assert!(metadata_tags.contains(&vec![ + "supported_kinds".to_string(), + "78".to_string(), + "30078".to_string(), + KIND_FARM_FILE_METADATA.to_string() + ])); + assert_tags_json(group_admins_tags( + &serde_json::to_string(&RadrootsGroupAdmins { + d_tag: "field-group".to_string(), + description: Some("group admins".to_string()), + admins: vec![sample_group_user("admin")], + }) + .expect("admins json"), + )); + assert_tags_json(group_members_tags( + &serde_json::to_string(&RadrootsGroupMembers { + d_tag: "field-group".to_string(), + description: Some("group members".to_string()), + members: vec![sample_group_user("member")], + }) + .expect("members json"), + )); + assert_tags_json(group_roles_tags( + &serde_json::to_string(&RadrootsGroupRoles { + d_tag: "field-group".to_string(), + description: Some("group roles".to_string()), + roles: vec![sample_group_role()], + }) + .expect("roles json"), + )); + } + + #[test] + fn listing_bindings_surface_builder_errors() { + let mut listing_json = serde_json::to_value(sample_listing()).expect("listing value"); + listing_json["bins"] = serde_json::Value::Array(Vec::new()); + let listing_json = serde_json::to_string(&listing_json).expect("listing json"); + + assert!(listing_tags(&listing_json).is_err()); + assert!(listing_tags_full(&listing_json).is_err()); + } +} diff --git a/crates/replica_schema_bindings/Cargo.toml b/crates/replica_schema_bindings/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "radroots_replica_schema_bindings" +description = "Generated bindings for Radroots replica schemas" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true +publish = false + +[dependencies] +dto_bindgen_core = { workspace = true } +radroots_replica_schema = { workspace = true, features = ["dto-bindgen"] } diff --git a/crates/replica_schema_bindings/src/lib.rs b/crates/replica_schema_bindings/src/lib.rs @@ -0,0 +1,31 @@ +pub use radroots_replica_schema as upstream; + +pub fn dto_registry() -> dto_bindgen_core::Registry { + upstream::dto::dto_registry() +} + +#[cfg(test)] +mod tests { + use super::dto_registry; + + #[test] + fn preserves_replica_schema_registry_exports() { + let registry = dto_registry(); + let actual = registry + .types_by_id + .values() + .map(|type_def| match type_def { + dto_bindgen_core::TypeDef::Struct(def) => def.export_name.as_str(), + dto_bindgen_core::TypeDef::Enum(def) => def.export_name.as_str(), + }) + .collect::<Vec<_>>(); + + assert!(actual.contains(&"Farm")); + assert!(actual.contains(&"GcsLocation")); + assert!(actual.contains(&"IGcsLocationFindMany")); + assert!(actual.contains(&"IGcsLocationFindManyResolve")); + assert!(actual.contains(&"IMediaImageFindMany")); + assert!(actual.contains(&"INostrProfileFindMany")); + assert!(actual.contains(&"INostrRelayFindMany")); + } +} diff --git a/crates/replica_store_wasm/Cargo.toml b/crates/replica_store_wasm/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "radroots_replica_store_wasm" +publish = false +version = "0.1.0-alpha.2" +edition.workspace = true +authors = ["Tyson Lupul <tyson@radroots.org>"] +rust-version.workspace = true +license.workspace = true +description = "WASM boundary for Radroots replica store access" +repository.workspace = true +homepage.workspace = true +readme = "README" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +radroots_sql_core = { workspace = true, features = ["web"] } +radroots_sdk_sql_wasm_runtime = { workspace = true } +radroots_replica_store = { workspace = true } +radroots_replica_schema = { workspace = true } +radroots_replica_sync = { workspace = true, features = ["std"] } +js-sys = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +serde-wasm-bindgen = { workspace = true } +wasm-bindgen = { workspace = true } + +[dev-dependencies] +wasm-bindgen-test = { workspace = true } + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] } diff --git a/crates/replica_store_wasm/README b/crates/replica_store_wasm/README @@ -0,0 +1,25 @@ +# radroots_replica_store_wasm + +This is the README for `radroots_replica_store_wasm`, which provides WebAssembly +bindings for `radroots_replica_store` in the `radroots` core libraries. + +## Overview + + * a wasm32-only wrapper around the replica store runtime surface; + * integration with `radroots_sql_wasm_core` for browser and worker SQL + execution; + * a small target-specific entry point layer rather than a separate database + implementation; + * intended for JavaScript-facing callers that need the replica store APIs + in wasm builds. + +## Copyright + +Except as otherwise noted, all files in the `radroots_replica_store_wasm` +distribution are + + Copyright (c) 2026 Tyson Lupul + +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see LICENSE included in the `radroots_replica_store_wasm` +distribution. diff --git a/crates/replica_store_wasm/src/lib.rs b/crates/replica_store_wasm/src/lib.rs @@ -0,0 +1,10 @@ +#![forbid(unsafe_code)] + +mod snapshot; +#[cfg(target_arch = "wasm32")] +mod utils; +#[cfg(target_arch = "wasm32")] +mod wasm_impl; +pub use snapshot::*; +#[cfg(target_arch = "wasm32")] +pub use wasm_impl::*; diff --git a/crates/replica_store_wasm/src/snapshot.rs b/crates/replica_store_wasm/src/snapshot.rs @@ -0,0 +1,87 @@ +use radroots_replica_store::ReplicaStoreExportManifestRs; + +pub const EXPORT_MANIFEST_FIELD: &str = "manifest_rs"; +pub const EXPORT_DB_BYTES_FIELD: &str = "db_bytes"; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ExportManifestSummary { + pub export_version: String, + pub replica_store_version: String, + pub backup_format_version: String, + pub schema_hash: String, + pub schema_table_count: usize, + pub migration_count: usize, + pub table_count_count: usize, +} + +pub fn synced_export_error(pending_count: usize, expected_count: usize) -> Option<String> { + if pending_count == 0 { + None + } else { + Some(format!( + "replica store export requires synced state (pending {pending_count}/{expected_count})" + )) + } +} + +pub fn export_manifest_summary(manifest: &ReplicaStoreExportManifestRs) -> ExportManifestSummary { + ExportManifestSummary { + export_version: manifest.export_version.clone(), + replica_store_version: manifest.replica_store_version.clone(), + backup_format_version: manifest.backup_format_version.clone(), + schema_hash: manifest.schema_hash.clone(), + schema_table_count: manifest.schema.len(), + migration_count: manifest.migrations.len(), + table_count_count: manifest.table_counts.len(), + } +} + +#[cfg(test)] +mod tests { + use super::{ + EXPORT_DB_BYTES_FIELD, EXPORT_MANIFEST_FIELD, export_manifest_summary, synced_export_error, + }; + + fn manifest() -> radroots_replica_store::ReplicaStoreExportManifestRs { + radroots_replica_store::ReplicaStoreExportManifestRs { + export_version: "1".to_owned(), + replica_store_version: "0.1.0".to_owned(), + backup_format_version: "1".to_owned(), + schema_hash: "schema-hash".to_owned(), + schema: Vec::new(), + migrations: Vec::new(), + table_counts: Vec::new(), + } + } + + #[test] + fn export_snapshot_field_names_are_stable() { + assert_eq!(EXPORT_MANIFEST_FIELD, "manifest_rs"); + assert_eq!(EXPORT_DB_BYTES_FIELD, "db_bytes"); + } + + #[test] + fn synced_export_error_allows_empty_pending_queue() { + assert_eq!(synced_export_error(0, 4), None); + } + + #[test] + fn synced_export_error_reports_pending_and_expected_counts() { + assert_eq!( + synced_export_error(2, 4).expect("error"), + "replica store export requires synced state (pending 2/4)" + ); + } + + #[test] + fn export_manifest_summary_preserves_versions_and_counts() { + let summary = export_manifest_summary(&manifest()); + assert_eq!(summary.export_version, "1"); + assert_eq!(summary.replica_store_version, "0.1.0"); + assert_eq!(summary.backup_format_version, "1"); + assert_eq!(summary.schema_hash, "schema-hash"); + assert_eq!(summary.schema_table_count, 0); + assert_eq!(summary.migration_count, 0); + assert_eq!(summary.table_count_count, 0); + } +} diff --git a/crates/replica_store_wasm/src/utils.rs b/crates/replica_store_wasm/src/utils.rs @@ -0,0 +1,13 @@ +use serde::Serialize; +use wasm_bindgen::prelude::*; + +use radroots_sql_core::SqlError; + +pub fn value_to_js<T>(value: T) -> Result<JsValue, JsValue> +where + T: Serialize, +{ + let json = serde_json::to_string(&value) + .map_err(|err| radroots_sdk_sql_wasm_runtime::err_js(SqlError::from(err)))?; + Ok(JsValue::from_str(&json)) +} diff --git a/crates/replica_store_wasm/src/wasm_impl.rs b/crates/replica_store_wasm/src/wasm_impl.rs @@ -0,0 +1,914 @@ +use crate::{ + snapshot::{EXPORT_DB_BYTES_FIELD, EXPORT_MANIFEST_FIELD, synced_export_error}, + utils::value_to_js, +}; +use radroots_replica_store::migrations; +use radroots_replica_store::{ReplicaStoreExportManifestRs, export_manifest}; +use radroots_replica_sync::radroots_replica_sync_status; +use radroots_sdk_sql_wasm_runtime::parse_json; +use radroots_sdk_sql_wasm_runtime::{ + WasmSqlExecutor, err_js, export_bytes, export_lock_begin, export_lock_end, + with_export_lock_bypass, +}; +use wasm_bindgen::JsValue; +use wasm_bindgen::prelude::*; + +use radroots_replica_schema::farm::{ + IFarmCreate, IFarmDelete, IFarmFindMany, IFarmFindOne, IFarmUpdate, +}; + +use radroots_replica_schema::farm_gcs_location::{ + IFarmGcsLocationCreate, IFarmGcsLocationDelete, IFarmGcsLocationFindMany, + IFarmGcsLocationFindOne, IFarmGcsLocationUpdate, +}; + +use radroots_replica_schema::farm_member::{ + IFarmMemberCreate, IFarmMemberDelete, IFarmMemberFindMany, IFarmMemberFindOne, + IFarmMemberUpdate, +}; + +use radroots_replica_schema::farm_member_claim::{ + IFarmMemberClaimCreate, IFarmMemberClaimDelete, IFarmMemberClaimFindMany, + IFarmMemberClaimFindOne, IFarmMemberClaimUpdate, +}; + +use radroots_replica_schema::farm_tag::{ + IFarmTagCreate, IFarmTagDelete, IFarmTagFindMany, IFarmTagFindOne, IFarmTagUpdate, +}; + +use radroots_replica_schema::gcs_location::{ + IGcsLocationCreate, IGcsLocationDelete, IGcsLocationFindMany, IGcsLocationFindOne, + IGcsLocationUpdate, +}; + +use radroots_replica_schema::log_error::{ + ILogErrorCreate, ILogErrorDelete, ILogErrorFindMany, ILogErrorFindOne, ILogErrorUpdate, +}; + +use radroots_replica_schema::media_image::{ + IMediaImageCreate, IMediaImageDelete, IMediaImageFindMany, IMediaImageFindOne, + IMediaImageUpdate, +}; + +use radroots_replica_schema::nostr_profile::{ + INostrProfileCreate, INostrProfileDelete, INostrProfileFindMany, INostrProfileFindOne, + INostrProfileUpdate, +}; + +use radroots_replica_schema::nostr_event_head::{ + INostrEventHeadCreate, INostrEventHeadDelete, INostrEventHeadFindMany, INostrEventHeadFindOne, + INostrEventHeadUpdate, +}; + +use radroots_replica_schema::nostr_relay::{ + INostrRelayCreate, INostrRelayDelete, INostrRelayFindMany, INostrRelayFindOne, + INostrRelayUpdate, +}; + +use radroots_replica_schema::trade_product::{ + ITradeProductCreate, ITradeProductDelete, ITradeProductFindMany, ITradeProductFindOne, + ITradeProductUpdate, +}; + +use radroots_replica_schema::plot::{ + IPlotCreate, IPlotDelete, IPlotFindMany, IPlotFindOne, IPlotUpdate, +}; + +use radroots_replica_schema::plot_gcs_location::{ + IPlotGcsLocationCreate, IPlotGcsLocationDelete, IPlotGcsLocationFindMany, + IPlotGcsLocationFindOne, IPlotGcsLocationUpdate, +}; + +use radroots_replica_schema::plot_tag::{ + IPlotTagCreate, IPlotTagDelete, IPlotTagFindMany, IPlotTagFindOne, IPlotTagUpdate, +}; + +use radroots_replica_schema::nostr_profile_relay::INostrProfileRelayRelation; + +use radroots_replica_schema::trade_product_location::ITradeProductLocationRelation; + +use radroots_replica_schema::trade_product_media::ITradeProductMediaRelation; + +#[wasm_bindgen(js_name = replica_store_run_migrations)] +pub fn replica_store_run_migrations() -> Result<(), JsValue> { + let exec = WasmSqlExecutor::new(); + migrations::run_all_up(&exec).map_err(err_js) +} + +#[wasm_bindgen(js_name = replica_store_reset_database)] +pub fn replica_store_reset_database() -> Result<(), JsValue> { + let exec = WasmSqlExecutor::new(); + migrations::run_all_down(&exec).map_err(err_js) +} + +#[wasm_bindgen(js_name = replica_store_export_json)] +pub fn replica_store_export_json() -> Result<JsValue, JsValue> { + let exec = WasmSqlExecutor::new(); + let dump = radroots_replica_store::backup::export_database_backup(&exec).map_err(err_js)?; + value_to_js(dump) +} + +#[wasm_bindgen(js_name = replica_store_import_json)] +pub fn replica_store_import_json(dump_json: &str) -> Result<(), JsValue> { + let exec = WasmSqlExecutor::new(); + radroots_replica_store::backup::restore_database_backup_json(&exec, dump_json).map_err(err_js) +} + +#[wasm_bindgen(js_name = replica_store_export_begin)] +pub fn replica_store_export_begin() -> Result<JsValue, JsValue> { + export_lock_begin().map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let result = with_export_lock_bypass(|| export_snapshot(&exec)); + match result { + Ok(value) => Ok(value), + Err(err) => { + export_lock_end(); + Err(err) + } + } +} + +#[wasm_bindgen(js_name = replica_store_export_finish)] +pub fn replica_store_export_finish() -> Result<(), JsValue> { + export_lock_end(); + Ok(()) +} + +fn export_snapshot(exec: &WasmSqlExecutor) -> Result<JsValue, JsValue> { + let status = radroots_replica_sync_status(exec).map_err(|err| { + err_js(radroots_sql_core::SqlError::InvalidArgument( + err.to_string(), + )) + })?; + if let Some(message) = synced_export_error(status.pending_count, status.expected_count) { + return Err(err_js(radroots_sql_core::SqlError::InvalidArgument( + message, + ))); + } + let manifest = export_manifest(exec).map_err(err_js)?; + export_snapshot_value(manifest) +} + +fn export_snapshot_value(manifest: ReplicaStoreExportManifestRs) -> Result<JsValue, JsValue> { + let bytes_js = export_bytes(); + export_snapshot_value_with_bytes(manifest, bytes_js) +} + +fn export_snapshot_value_with_bytes( + manifest: ReplicaStoreExportManifestRs, + bytes_js: JsValue, +) -> Result<JsValue, JsValue> { + let manifest_js = serde_wasm_bindgen::to_value(&manifest).map_err(|err| { + err_js(radroots_sql_core::SqlError::SerializationError( + err.to_string(), + )) + })?; + let obj = js_sys::Object::new(); + js_sys::Reflect::set( + &obj, + &JsValue::from_str(EXPORT_MANIFEST_FIELD), + &manifest_js, + ) + .map_err(|_| err_js(radroots_sql_core::SqlError::Internal))?; + js_sys::Reflect::set(&obj, &JsValue::from_str(EXPORT_DB_BYTES_FIELD), &bytes_js) + .map_err(|_| err_js(radroots_sql_core::SqlError::Internal))?; + Ok(JsValue::from(obj)) +} + +#[cfg(all(test, target_arch = "wasm32"))] +mod tests { + use super::export_snapshot_value_with_bytes; + use js_sys::{Reflect, Uint8Array}; + use wasm_bindgen::JsValue; + + #[wasm_bindgen_test::wasm_bindgen_test] + fn export_snapshot_value_includes_fields() { + let manifest = radroots_replica_store::ReplicaStoreExportManifestRs { + export_version: "1".to_string(), + replica_store_version: "0.0.0".to_string(), + backup_format_version: "0.0.0".to_string(), + schema_hash: "hash".to_string(), + schema: Vec::new(), + migrations: Vec::new(), + table_counts: Vec::new(), + }; + let bytes = Uint8Array::new_with_length(2); + let js = + export_snapshot_value_with_bytes(manifest, JsValue::from(bytes)).expect("snapshot"); + let manifest_rs = + Reflect::get(&js, &JsValue::from_str("manifest_rs")).expect("manifest_rs"); + let db_bytes = Reflect::get(&js, &JsValue::from_str("db_bytes")).expect("db_bytes"); + assert!(manifest_rs.is_object()); + assert!(db_bytes.is_object()); + } +} + +#[wasm_bindgen(js_name = replica_store_farm_create)] +pub fn replica_store_farm_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_find_one)] +pub fn replica_store_farm_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_find_many)] +pub fn replica_store_farm_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_update)] +pub fn replica_store_farm_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_delete)] +pub fn replica_store_farm_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_create)] +pub fn replica_store_plot_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_find_one)] +pub fn replica_store_plot_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_find_many)] +pub fn replica_store_plot_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_update)] +pub fn replica_store_plot_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_delete)] +pub fn replica_store_plot_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_gcs_location_create)] +pub fn replica_store_gcs_location_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IGcsLocationCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::gcs_location::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_gcs_location_find_one)] +pub fn replica_store_gcs_location_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IGcsLocationFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::gcs_location::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_gcs_location_find_many)] +pub fn replica_store_gcs_location_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IGcsLocationFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::gcs_location::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_gcs_location_update)] +pub fn replica_store_gcs_location_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IGcsLocationUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::gcs_location::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_gcs_location_delete)] +pub fn replica_store_gcs_location_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IGcsLocationDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::gcs_location::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_gcs_location_create)] +pub fn replica_store_farm_gcs_location_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmGcsLocationCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_gcs_location::create(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_gcs_location_find_one)] +pub fn replica_store_farm_gcs_location_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmGcsLocationFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_gcs_location::find_one(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_gcs_location_find_many)] +pub fn replica_store_farm_gcs_location_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmGcsLocationFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_gcs_location::find_many(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_gcs_location_update)] +pub fn replica_store_farm_gcs_location_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmGcsLocationUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_gcs_location::update(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_gcs_location_delete)] +pub fn replica_store_farm_gcs_location_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmGcsLocationDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_gcs_location::delete(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_gcs_location_create)] +pub fn replica_store_plot_gcs_location_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotGcsLocationCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot_gcs_location::create(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_gcs_location_find_one)] +pub fn replica_store_plot_gcs_location_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotGcsLocationFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot_gcs_location::find_one(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_gcs_location_find_many)] +pub fn replica_store_plot_gcs_location_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotGcsLocationFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot_gcs_location::find_many(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_gcs_location_update)] +pub fn replica_store_plot_gcs_location_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotGcsLocationUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot_gcs_location::update(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_gcs_location_delete)] +pub fn replica_store_plot_gcs_location_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotGcsLocationDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot_gcs_location::delete(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_tag_create)] +pub fn replica_store_farm_tag_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmTagCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_tag::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_tag_find_one)] +pub fn replica_store_farm_tag_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmTagFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::farm_tag::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_tag_find_many)] +pub fn replica_store_farm_tag_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmTagFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::farm_tag::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_tag_update)] +pub fn replica_store_farm_tag_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmTagUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_tag::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_tag_delete)] +pub fn replica_store_farm_tag_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmTagDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_tag::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_tag_create)] +pub fn replica_store_plot_tag_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotTagCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot_tag::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_tag_find_one)] +pub fn replica_store_plot_tag_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotTagFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::plot_tag::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_tag_find_many)] +pub fn replica_store_plot_tag_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotTagFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::plot_tag::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_tag_update)] +pub fn replica_store_plot_tag_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotTagUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot_tag::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_plot_tag_delete)] +pub fn replica_store_plot_tag_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IPlotTagDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::plot_tag::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_create)] +pub fn replica_store_farm_member_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::farm_member::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_find_one)] +pub fn replica_store_farm_member_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::farm_member::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_find_many)] +pub fn replica_store_farm_member_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::farm_member::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_update)] +pub fn replica_store_farm_member_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::farm_member::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_delete)] +pub fn replica_store_farm_member_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::farm_member::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_claim_create)] +pub fn replica_store_farm_member_claim_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberClaimCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_member_claim::create(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_claim_find_one)] +pub fn replica_store_farm_member_claim_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberClaimFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_member_claim::find_one(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_claim_find_many)] +pub fn replica_store_farm_member_claim_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberClaimFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_member_claim::find_many(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_claim_update)] +pub fn replica_store_farm_member_claim_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberClaimUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_member_claim::update(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_farm_member_claim_delete)] +pub fn replica_store_farm_member_claim_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IFarmMemberClaimDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::farm_member_claim::delete(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_log_error_create)] +pub fn replica_store_log_error_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ILogErrorCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::log_error::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_log_error_find_one)] +pub fn replica_store_log_error_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ILogErrorFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::log_error::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_log_error_find_many)] +pub fn replica_store_log_error_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ILogErrorFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::log_error::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_log_error_update)] +pub fn replica_store_log_error_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ILogErrorUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::log_error::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_log_error_delete)] +pub fn replica_store_log_error_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ILogErrorDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::log_error::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_media_image_create)] +pub fn replica_store_media_image_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IMediaImageCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::media_image::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_media_image_find_one)] +pub fn replica_store_media_image_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IMediaImageFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::media_image::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_media_image_find_many)] +pub fn replica_store_media_image_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IMediaImageFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::media_image::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_media_image_update)] +pub fn replica_store_media_image_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IMediaImageUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::media_image::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_media_image_delete)] +pub fn replica_store_media_image_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: IMediaImageDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::media_image::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_profile_create)] +pub fn replica_store_nostr_profile_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrProfileCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_profile::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_profile_find_one)] +pub fn replica_store_nostr_profile_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrProfileFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_profile::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_profile_find_many)] +pub fn replica_store_nostr_profile_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrProfileFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::nostr_profile::find_many(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_profile_update)] +pub fn replica_store_nostr_profile_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrProfileUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_profile::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_profile_delete)] +pub fn replica_store_nostr_profile_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrProfileDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_profile::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_event_head_create)] +pub fn replica_store_nostr_event_head_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrEventHeadCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::nostr_event_head::create(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_event_head_find_one)] +pub fn replica_store_nostr_event_head_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrEventHeadFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::nostr_event_head::find_one(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_event_head_find_many)] +pub fn replica_store_nostr_event_head_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrEventHeadFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::nostr_event_head::find_many(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_event_head_update)] +pub fn replica_store_nostr_event_head_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrEventHeadUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::nostr_event_head::update(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_event_head_delete)] +pub fn replica_store_nostr_event_head_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrEventHeadDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::nostr_event_head::delete(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_relay_create)] +pub fn replica_store_nostr_relay_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrRelayCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_relay::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_relay_find_one)] +pub fn replica_store_nostr_relay_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrRelayFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_relay::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_relay_find_many)] +pub fn replica_store_nostr_relay_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrRelayFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_relay::find_many(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_relay_update)] +pub fn replica_store_nostr_relay_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrRelayUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_relay::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_relay_delete)] +pub fn replica_store_nostr_relay_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrRelayDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::nostr_relay::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_create)] +pub fn replica_store_trade_product_create(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductCreate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::trade_product::create(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_find_one)] +pub fn replica_store_trade_product_find_one(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductFindOne = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::trade_product::find_one(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_find_many)] +pub fn replica_store_trade_product_find_many(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductFindMany = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::trade_product::find_many(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_update)] +pub fn replica_store_trade_product_update(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductUpdate = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::trade_product::update(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_delete)] +pub fn replica_store_trade_product_delete(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductDelete = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = + radroots_replica_store::trade_product::delete(&exec, &opts).map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_profile_relay_set)] +pub fn replica_store_nostr_profile_relay_set(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrProfileRelayRelation = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::nostr_profile_relay::set(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_nostr_profile_relay_unset)] +pub fn replica_store_nostr_profile_relay_unset(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: INostrProfileRelayRelation = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::nostr_profile_relay::unset(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_location_set)] +pub fn replica_store_trade_product_location_set(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductLocationRelation = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::trade_product_location::set(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_location_unset)] +pub fn replica_store_trade_product_location_unset(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductLocationRelation = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::trade_product_location::unset(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_media_set)] +pub fn replica_store_trade_product_media_set(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductMediaRelation = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::trade_product_media::set(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} + +#[wasm_bindgen(js_name = replica_store_trade_product_media_unset)] +pub fn replica_store_trade_product_media_unset(opts_json: &str) -> Result<JsValue, JsValue> { + let opts: ITradeProductMediaRelation = parse_json(opts_json).map_err(err_js)?; + let exec = WasmSqlExecutor::new(); + let out = radroots_replica_store::trade_product_media::unset(&exec, &opts) + .map_err(|e| err_js(e.err))?; + value_to_js(out) +} diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml @@ -187,10 +187,10 @@ nostr = { workspace = true } radroots_core = { workspace = true, default-features = false, features = [ "std", ] } -radroots_replica_db = { workspace = true, default-features = false, features = [ +radroots_replica_store = { workspace = true, default-features = false, features = [ "native", ] } -radroots_replica_db_schema = { workspace = true } +radroots_replica_schema = { workspace = true } radroots_replica_sync = { workspace = true, features = ["std"] } radroots_sql_core = { workspace = true, features = ["native"] } radroots_nostr = { workspace = true, default-features = false, features = [ diff --git a/crates/sdk/tests/replica_ingest.rs b/crates/sdk/tests/replica_ingest.rs @@ -1,6 +1,6 @@ use radroots_event::{RadrootsEventEnvelope, farm::RadrootsFarm}; -use radroots_replica_db::ReplicaSql; -use radroots_replica_db_schema::farm::IFarmFindMany; +use radroots_replica_schema::farm::IFarmFindMany; +use radroots_replica_store::ReplicaSql; use radroots_replica_sync::{RadrootsReplicaIngestOutcome, radroots_replica_ingest_event}; use radroots_sql_core::{SqlExecutor, SqliteExecutor}; use tempfile::{TempDir, tempdir}; diff --git a/crates/sdk/tests/runtime_foundation.rs b/crates/sdk/tests/runtime_foundation.rs @@ -1047,7 +1047,7 @@ fn sdk_examples_stay_on_product_api_boundary() { for (name, example) in examples { assert!(!example.contains("WireEventParts"), "{name}"); assert!(!example.contains("protocol::wire"), "{name}"); - assert!(!example.contains("events_codec::wire"), "{name}"); + assert!(!example.contains("event_codec::wire"), "{name}"); assert!(!example.contains(".as_wire_parts("), "{name}"); assert!(!example.contains(".into_wire_parts("), "{name}"); } diff --git a/crates/sdk/tests/source_boundary.rs b/crates/sdk/tests/source_boundary.rs @@ -1904,8 +1904,8 @@ fn sdk_transport_policy_sources_reject_configured_profile_and_proxy_relay_bridge "src", "tests", "examples", - "packages/events-bindings/src", - "packages/events-codec-js/src", + "packages/event-bindings/src", + "packages/event-codec-js/src", ] { let root = manifest_dir.join(relative_path); if !root.exists() { diff --git a/tools/sdk_xtask_import/Cargo.toml b/tools/sdk_xtask_import/Cargo.toml @@ -18,10 +18,10 @@ dto_bindgen_backend_ts = { workspace = true } dto_bindgen_core = { workspace = true } radroots_core = { workspace = true, features = ["dto-bindgen"] } radroots_event = { workspace = true, features = ["dto-bindgen"] } -radroots_events_bindings = { path = "../../crates/events_bindings" } +radroots_event_bindings = { path = "../../crates/event_bindings" } radroots_event_index = { workspace = true, features = ["dto-bindgen"] } radroots_identity_bindings = { path = "../../crates/identity_bindings" } -radroots_replica_db_schema_bindings = { path = "../../crates/replica_db_schema_bindings" } +radroots_replica_schema_bindings = { path = "../../crates/replica_schema_bindings" } radroots_trade_bindings = { path = "../../crates/trade_bindings" } flate2 = "1" serde_json = "1" diff --git a/tools/sdk_xtask_import/src/check.rs b/tools/sdk_xtask_import/src/check.rs @@ -2141,13 +2141,13 @@ transport-reticulum-preview = [] fn consumer_smoke_script_imports_package_roots() { let script = consumer_smoke_script(&[ "@radroots/core-bindings".to_owned(), - "@radroots/events-codec-wasm".to_owned(), + "@radroots/event-codec-wasm".to_owned(), ]) .expect("smoke script renders"); assert_eq!( script, - "await import(\"@radroots/core-bindings\");\nawait import(\"@radroots/events-codec-wasm\");\n" + "await import(\"@radroots/core-bindings\");\nawait import(\"@radroots/event-codec-wasm\");\n" ); } @@ -2221,12 +2221,12 @@ transport-reticulum-preview = [] let source = package_json_value(&package_json_with_dependencies( "trade-bindings", r#""@radroots/core-bindings": "workspace:^", - "@radroots/events-bindings": "workspace:^""#, + "@radroots/event-bindings": "workspace:^""#, )); let packed = package_json_value(&package_json_with_dependencies( "trade-bindings", r#""@radroots/core-bindings": "^0.1.0", - "@radroots/events-bindings": "^0.1.0""#, + "@radroots/event-bindings": "^0.1.0""#, )); check_packed_package_json( diff --git a/tools/sdk_xtask_import/src/contracts.rs b/tools/sdk_xtask_import/src/contracts.rs @@ -575,13 +575,13 @@ repository = "sdk-typescript" [packages] "radroots_core" = "@radroots/core-bindings" -"radroots_event" = "@radroots/events-bindings" -"radroots_event_index" = "@radroots/events-indexed-bindings" +"radroots_event" = "@radroots/event-bindings" +"radroots_event_index" = "@radroots/event-index-bindings" "radroots_identity" = "@radroots/identity-bindings" -"radroots_replica_db_schema" = "@radroots/replica-db-schema-bindings" +"radroots_replica_schema" = "@radroots/replica-schema-bindings" "radroots_trade" = "@radroots/trade-bindings" -"radroots_events_codec_wasm" = "@radroots/events-codec-wasm" -"radroots_replica_db_wasm" = "@radroots/replica-db-wasm" +"radroots_event_codec_wasm" = "@radroots/event-codec-wasm" +"radroots_replica_store_wasm" = "@radroots/replica-store-wasm" "radroots_replica_sync_wasm" = "@radroots/replica-sync-wasm" [artifacts] @@ -614,19 +614,19 @@ crate_dir = "crates/core_bindings" package = "@radroots/core-bindings" package_dir = "packages/core-bindings" -[npm_packages.events] +[npm_packages.event] kind = "bindings" -crate_name = "radroots_events_bindings" -crate_dir = "crates/events_bindings" -package = "@radroots/events-bindings" -package_dir = "packages/events-bindings" +crate_name = "radroots_event_bindings" +crate_dir = "crates/event_bindings" +package = "@radroots/event-bindings" +package_dir = "packages/event-bindings" -[npm_packages.events_indexed] +[npm_packages.event_index] kind = "bindings" -crate_name = "radroots_events_indexed_bindings" -crate_dir = "crates/events_indexed_bindings" -package = "@radroots/events-indexed-bindings" -package_dir = "packages/events-indexed-bindings" +crate_name = "radroots_event_index_bindings" +crate_dir = "crates/event_index_bindings" +package = "@radroots/event-index-bindings" +package_dir = "packages/event-index-bindings" [npm_packages.identity] kind = "bindings" @@ -635,12 +635,12 @@ crate_dir = "crates/identity_bindings" package = "@radroots/identity-bindings" package_dir = "packages/identity-bindings" -[npm_packages.replica_db_schema] +[npm_packages.replica_schema] kind = "bindings" -crate_name = "radroots_replica_db_schema_bindings" -crate_dir = "crates/replica_db_schema_bindings" -package = "@radroots/replica-db-schema-bindings" -package_dir = "packages/replica-db-schema-bindings" +crate_name = "radroots_replica_schema_bindings" +crate_dir = "crates/replica_schema_bindings" +package = "@radroots/replica-schema-bindings" +package_dir = "packages/replica-schema-bindings" [npm_packages.trade] kind = "bindings" @@ -649,23 +649,23 @@ crate_dir = "crates/trade_bindings" package = "@radroots/trade-bindings" package_dir = "packages/trade-bindings" -[npm_packages.events_codec] +[npm_packages.event_codec] kind = "wasm" -crate_name = "radroots_events_codec_wasm" -crate_dir = "crates/events_codec_wasm" -package = "@radroots/events-codec-wasm" -package_dir = "packages/events-codec-wasm" -out_name = "radroots_events_codec_wasm" -out_dir = "../../packages/events-codec-wasm/dist" - -[npm_packages.replica_db] +crate_name = "radroots_event_codec_wasm" +crate_dir = "crates/event_codec_wasm" +package = "@radroots/event-codec-wasm" +package_dir = "packages/event-codec-wasm" +out_name = "radroots_event_codec_wasm" +out_dir = "../../packages/event-codec-wasm/dist" + +[npm_packages.replica_store] kind = "wasm" -crate_name = "radroots_replica_db_wasm" -crate_dir = "crates/replica_db_wasm" -package = "@radroots/replica-db-wasm" -package_dir = "packages/replica-db-wasm" -out_name = "radroots_replica_db_wasm" -out_dir = "../../packages/replica-db-wasm/dist" +crate_name = "radroots_replica_store_wasm" +crate_dir = "crates/replica_store_wasm" +package = "@radroots/replica-store-wasm" +package_dir = "packages/replica-store-wasm" +out_name = "radroots_replica_store_wasm" +out_dir = "../../packages/replica-store-wasm/dist" [npm_packages.replica_sync] kind = "wasm" diff --git a/tools/sdk_xtask_import/src/dto_roots.rs b/tools/sdk_xtask_import/src/dto_roots.rs @@ -46,8 +46,8 @@ struct DtoExternalOverride { const CORE_BINDINGS_PACKAGE_KEY: &str = "core"; const CORE_BINDINGS_PACKAGE_NAME: &str = "@radroots/core-bindings"; -const EVENTS_BINDINGS_PACKAGE_KEY: &str = "events"; -const EVENTS_BINDINGS_PACKAGE_NAME: &str = "@radroots/events-bindings"; +const EVENT_BINDINGS_PACKAGE_KEY: &str = "event"; +const EVENT_BINDINGS_PACKAGE_NAME: &str = "@radroots/event-bindings"; pub const DTO_PACKAGE_ROOTS: &[DtoPackageRootSet] = &[ DtoPackageRootSet { @@ -55,12 +55,12 @@ pub const DTO_PACKAGE_ROOTS: &[DtoPackageRootSet] = &[ roots: core_roots, }, DtoPackageRootSet { - package_key: "events", - roots: events_roots, + package_key: "event", + roots: event_roots, }, DtoPackageRootSet { - package_key: "events_indexed", - roots: events_indexed_roots, + package_key: "event_index", + roots: event_index_roots, }, DtoPackageRootSet { package_key: "trade", @@ -75,17 +75,17 @@ pub const MANUAL_DESCRIPTOR_FAMILIES: &[ManualDescriptorFamily] = &[ reason: "custom serde, string-backed newtypes, aliases, and tagged enum wire forms require source-owned manual descriptors", }, ManualDescriptorFamily { - package_key: "events", + package_key: "event", source_family: "event timestamps, counters, and optional metadata fields", reason: "large integers and source-specific optional/null policy must be explicit", }, ManualDescriptorFamily { - package_key: "events", + package_key: "event", source_family: "GeoJSON coordinate arrays", reason: "fixed-size Rust arrays must preserve tuple semantics in TypeScript", }, ManualDescriptorFamily { - package_key: "events_indexed", + package_key: "event_index", source_family: "checkpoint and index cursor fields", reason: "custom deserialization and large integers require manual descriptor policy", }, @@ -95,7 +95,7 @@ pub const MANUAL_DESCRIPTOR_FAMILIES: &[ManualDescriptorFamily] = &[ reason: "core aliases, source-owned event imports, and count-family numeric policy require explicit descriptors", }, ManualDescriptorFamily { - package_key: "replica_db_schema", + package_key: "replica_schema", source_family: "untagged query wrappers and serde_json value fields", reason: "schema query shapes are generated and not all source fields map to derive-supported DTOs", }, @@ -108,12 +108,12 @@ pub const SDK_LOCAL_WRAPPER_ALLOWANCES: &[SdkLocalWrapperAllowance] = &[ reason: "source descriptors correctly describe fields as strings, while package roots still need stable named TypeScript aliases", }, SdkLocalWrapperAllowance { - package_key: "replica_db_schema", + package_key: "replica_schema", shape_family: "generated query argument wrappers", reason: "schema operation inputs are generated package shapes rather than source-owned public DTO structs", }, SdkLocalWrapperAllowance { - package_key: "events_indexed", + package_key: "event_index", shape_family: "RadrootsEventIndexShardId package alias", reason: "source descriptors correctly describe the shard id newtype as a string, while package roots still need a stable named TypeScript alias", }, @@ -133,32 +133,32 @@ const TRADE_EXTERNAL_OVERRIDES: &[DtoExternalOverride] = &[ core_override("RadrootsCoreQuantity"), core_override("RadrootsCoreQuantityPrice"), core_override("RadrootsCoreUnit"), - events_override("RadrootsFarmRef"), - events_override("RadrootsListing"), - events_override("RadrootsListingAvailability"), - events_override("RadrootsListingBin"), - events_override("RadrootsListingDeliveryMethod"), - events_override("RadrootsListingImage"), - events_override("RadrootsListingProduct"), - events_override("RadrootsListingPublicLocation"), - events_override("RadrootsListingStatus"), - events_override("RadrootsEventPtr"), - events_override("RadrootsPlotRef"), - events_override("RadrootsResourceAreaRef"), - events_override("RadrootsOrderEconomicActor"), - events_override("RadrootsOrderEconomicEffect"), - events_override("RadrootsOrderEconomicItem"), - events_override("RadrootsOrderEconomicLine"), - events_override("RadrootsOrderEconomicLineKind"), - events_override("RadrootsOrderEconomics"), - events_override("RadrootsOrderEventType"), - events_override("RadrootsOrderInventoryCommitment"), - events_override("RadrootsOrderItem"), - events_override("RadrootsOrderPricingBasis"), + event_override("RadrootsFarmRef"), + event_override("RadrootsListing"), + event_override("RadrootsListingAvailability"), + event_override("RadrootsListingBin"), + event_override("RadrootsListingDeliveryMethod"), + event_override("RadrootsListingImage"), + event_override("RadrootsListingProduct"), + event_override("RadrootsListingPublicLocation"), + event_override("RadrootsListingStatus"), + event_override("RadrootsEventPtr"), + event_override("RadrootsPlotRef"), + event_override("RadrootsResourceAreaRef"), + event_override("RadrootsOrderEconomicActor"), + event_override("RadrootsOrderEconomicEffect"), + event_override("RadrootsOrderEconomicItem"), + event_override("RadrootsOrderEconomicLine"), + event_override("RadrootsOrderEconomicLineKind"), + event_override("RadrootsOrderEconomics"), + event_override("RadrootsOrderEventType"), + event_override("RadrootsOrderInventoryCommitment"), + event_override("RadrootsOrderItem"), + event_override("RadrootsOrderPricingBasis"), ]; const TRADE_REQUIRED_EXTERNAL_PACKAGE_IMPORTS: &[&str] = - &[CORE_BINDINGS_PACKAGE_NAME, EVENTS_BINDINGS_PACKAGE_NAME]; + &[CORE_BINDINGS_PACKAGE_NAME, EVENT_BINDINGS_PACKAGE_NAME]; pub fn package_root_set(package_key: &str) -> Option<&'static DtoPackageRootSet> { DTO_PACKAGE_ROOTS @@ -179,26 +179,25 @@ pub fn core_types_module() -> Result<DtoTypesModule, String> { )) } -pub fn events_types_module() -> Result<DtoTypesModule, String> { - let root_set = - package_root_set("events").ok_or_else(|| "missing events DTO roots".to_owned())?; +pub fn event_types_module() -> Result<DtoTypesModule, String> { + let root_set = package_root_set("event").ok_or_else(|| "missing event DTO roots".to_owned())?; let registry = root_set.registry(); let options = core_import_options(&registry, DtoRegistryRenderOptions::default())?; let rendered = render_registry_types(&registry, &options)?; - Ok(with_events_sdk_wrappers(rendered)) + Ok(with_event_sdk_wrappers(rendered)) } -pub fn events_indexed_types_module() -> Result<DtoTypesModule, String> { - let root_set = package_root_set("events_indexed") - .ok_or_else(|| "missing events-indexed DTO roots".to_owned())?; +pub fn event_index_types_module() -> Result<DtoTypesModule, String> { + let root_set = package_root_set("event_index") + .ok_or_else(|| "missing event-index DTO roots".to_owned())?; let rendered = render_registry_types(&root_set.registry(), &DtoRegistryRenderOptions::default())?; - Ok(with_events_indexed_sdk_wrappers(rendered)) + Ok(with_event_index_sdk_wrappers(rendered)) } -pub fn replica_db_schema_types_module() -> Result<DtoTypesModule, String> { +pub fn replica_schema_types_module() -> Result<DtoTypesModule, String> { render_registry_types( - &radroots_replica_db_schema_bindings::dto_registry(), + &radroots_replica_schema_bindings::dto_registry(), &DtoRegistryRenderOptions::default(), ) } @@ -216,11 +215,11 @@ fn core_roots() -> Vec<RootDescriptor> { radroots_core::dto::dto_roots().into_iter().collect() } -fn events_roots() -> Vec<RootDescriptor> { +fn event_roots() -> Vec<RootDescriptor> { radroots_event::dto::dto_roots().into_iter().collect() } -fn events_indexed_roots() -> Vec<RootDescriptor> { +fn event_index_roots() -> Vec<RootDescriptor> { radroots_event_index::dto::dto_roots().into_iter().collect() } @@ -295,8 +294,8 @@ fn generated_external_package_exports() -> Result<BTreeMap<&'static str, BTreeSe type_exports(core_types_module()?.body_ts()), ), ( - EVENTS_BINDINGS_PACKAGE_KEY, - type_exports(events_types_module()?.body_ts()), + EVENT_BINDINGS_PACKAGE_KEY, + type_exports(event_types_module()?.body_ts()), ), ])) } @@ -416,16 +415,16 @@ const fn core_override(export_name: &'static str) -> DtoExternalOverride { } } -const fn events_override(export_name: &'static str) -> DtoExternalOverride { +const fn event_override(export_name: &'static str) -> DtoExternalOverride { DtoExternalOverride { target_type: export_name, import_name: export_name, - from_package_key: EVENTS_BINDINGS_PACKAGE_KEY, - from: EVENTS_BINDINGS_PACKAGE_NAME, + from_package_key: EVENT_BINDINGS_PACKAGE_KEY, + from: EVENT_BINDINGS_PACKAGE_NAME, } } -fn with_events_sdk_wrappers(module: DtoTypesModule) -> DtoTypesModule { +fn with_event_sdk_wrappers(module: DtoTypesModule) -> DtoTypesModule { let mut declarations = module .body_ts() .split("\n\n") @@ -458,7 +457,7 @@ fn declaration_name(declaration: &str) -> &str { .unwrap_or(declaration) } -fn with_events_indexed_sdk_wrappers(module: DtoTypesModule) -> DtoTypesModule { +fn with_event_index_sdk_wrappers(module: DtoTypesModule) -> DtoTypesModule { let mut declarations = module .body_ts() .split("\n\n") @@ -524,43 +523,41 @@ mod tests { use super::{ CORE_BINDINGS_PACKAGE_KEY, CORE_BINDINGS_PACKAGE_NAME, DTO_PACKAGE_ROOTS, DtoExternalOverride, MANUAL_DESCRIPTOR_FAMILIES, SDK_LOCAL_WRAPPER_ALLOWANCES, - events_override, imported_type_inventory, package_root_set, trade_import_options, + event_override, imported_type_inventory, package_root_set, trade_import_options, type_exports, validate_external_override_target, validate_external_override_usage, with_checked_external_type, }; use dto_bindgen_backend_ts::{DtoRegistryRenderOptions, DtoTypesModule}; - const EVENTS_BINDINGS_TYPES_TS: &str = - include_str!("../../../packages/events-bindings/src/generated/types.ts"); - const EVENTS_INDEXED_BINDINGS_TYPES_TS: &str = - include_str!("../../../packages/events-indexed-bindings/src/generated/types.ts"); - const REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS: &str = - include_str!("../../../packages/replica-db-schema-bindings/src/generated/types.ts"); + const EVENT_BINDINGS_TYPES_TS: &str = + include_str!("../../../packages/event-bindings/src/generated/types.ts"); + const EVENT_INDEX_BINDINGS_TYPES_TS: &str = + include_str!("../../../packages/event-index-bindings/src/generated/types.ts"); + const REPLICA_SCHEMA_BINDINGS_TYPES_TS: &str = + include_str!("../../../packages/replica-schema-bindings/src/generated/types.ts"); const TRADE_BINDINGS_TYPES_TS: &str = include_str!("../../../packages/trade-bindings/src/generated/types.ts"); const REPLICA_SCHEMA_MODEL_SOURCES: &[&str] = &[ - include_str!("../../../../lib/crates/replica_db_schema/src/models/farm.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/farm_gcs_location.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/farm_member.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/farm_member_claim.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/farm_tag.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/gcs_location.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/log_error.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/media_image.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/nostr_event_head.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/nostr_profile.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/nostr_profile_relay.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/nostr_relay.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/plot.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/plot_gcs_location.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/plot_tag.rs"), - include_str!("../../../../lib/crates/replica_db_schema/src/models/trade_product.rs"), - include_str!( - "../../../../lib/crates/replica_db_schema/src/models/trade_product_location.rs" - ), - include_str!("../../../../lib/crates/replica_db_schema/src/models/trade_product_media.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/farm.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/farm_gcs_location.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/farm_member.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/farm_member_claim.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/farm_tag.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/gcs_location.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/log_error.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/media_image.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/nostr_event_head.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/nostr_profile.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/nostr_profile_relay.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/nostr_relay.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/plot.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/plot_gcs_location.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/plot_tag.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/trade_product.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/trade_product_location.rs"), + include_str!("../../../../lib/crates/replica_schema/src/models/trade_product_media.rs"), ]; - const EVENTS_TYPE_INVENTORY: &[&str] = &[ + const EVENT_TYPE_INVENTORY: &[&str] = &[ "JobFeedbackStatus", "JobInputType", "JobPaymentRequest", @@ -676,7 +673,7 @@ mod tests { "RadrootsWikiMergeRequest", "RadrootsWikiRedirect", ]; - const EVENTS_INDEXED_TYPE_INVENTORY: &[&str] = &[ + const EVENT_INDEX_TYPE_INVENTORY: &[&str] = &[ "RadrootsEventIndexShardId", "RadrootsEventIndexIdRange", "RadrootsEventIndexShardMetadata", @@ -737,8 +734,8 @@ mod tests { #[test] fn package_roots_are_explicit_not_discovered() { assert!(package_root_set("core").is_some()); - assert!(package_root_set("events").is_some()); - assert!(package_root_set("events_indexed").is_some()); + assert!(package_root_set("event").is_some()); + assert!(package_root_set("event_index").is_some()); assert!(package_root_set("trade").is_some()); } @@ -855,16 +852,15 @@ mod tests { #[test] fn external_override_usage_rejects_local_emission_for_imported_type() { let module = DtoTypesModule::new( - "import type { RadrootsCoreDecimal } from \"@radroots/core-bindings\";\n\nimport type { RadrootsFarmRef } from \"@radroots/events-bindings\";\n\n", + "import type { RadrootsCoreDecimal } from \"@radroots/core-bindings\";\n\nimport type { RadrootsFarmRef } from \"@radroots/event-bindings\";\n\n", "export type RadrootsFarmRef = { pubkey: string, d_tag: string, };", ); - let error = - validate_external_override_usage(&module, &[events_override("RadrootsFarmRef")]) - .expect_err("local emission of imported type must fail"); + let error = validate_external_override_usage(&module, &[event_override("RadrootsFarmRef")]) + .expect_err("local emission of imported type must fail"); assert_eq!( error, - "external DTO override `RadrootsFarmRef` from `@radroots/events-bindings` was emitted locally instead of imported" + "external DTO override `RadrootsFarmRef` from `@radroots/event-bindings` was emitted locally instead of imported" ); } @@ -893,17 +889,17 @@ mod tests { } #[test] - fn events_type_inventory_matches_current_package_surface() { - let actual = type_inventory(EVENTS_BINDINGS_TYPES_TS); + fn event_type_inventory_matches_current_package_surface() { + let actual = type_inventory(EVENT_BINDINGS_TYPES_TS); - assert_eq!(actual, EVENTS_TYPE_INVENTORY); + assert_eq!(actual, EVENT_TYPE_INVENTORY); } #[test] - fn events_indexed_type_inventory_matches_current_package_surface() { - let actual = type_inventory(EVENTS_INDEXED_BINDINGS_TYPES_TS); + fn event_index_type_inventory_matches_current_package_surface() { + let actual = type_inventory(EVENT_INDEX_BINDINGS_TYPES_TS); - assert_eq!(actual, EVENTS_INDEXED_TYPE_INVENTORY); + assert_eq!(actual, EVENT_INDEX_TYPE_INVENTORY); } #[test] @@ -914,28 +910,28 @@ mod tests { } #[test] - fn replica_db_schema_generated_types_preserve_source_schema_contracts() { - let actual = type_inventory(REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS); + fn replica_schema_generated_types_preserve_source_schema_contracts() { + let actual = type_inventory(REPLICA_SCHEMA_BINDINGS_TYPES_TS); let trade_product_filter = type_declaration( - REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS, + REPLICA_SCHEMA_BINDINGS_TYPES_TS, "ITradeProductFieldsFilter", ); let trade_product_partial = type_declaration( - REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS, + REPLICA_SCHEMA_BINDINGS_TYPES_TS, "ITradeProductFieldsPartial", ); assert!(actual.contains(&"Farm")); assert!(actual.contains(&"GcsLocation")); assert!(actual.contains(&"NostrEventHead")); - assert!(actual.contains(&"ReplicaDbJsonValue")); + assert!(actual.contains(&"ReplicaStoreJsonValue")); assert!(actual.contains(&"ITradeProductFieldsPartial")); assert!(!actual.contains(&"NostrEventState")); - assert!(REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS.contains( - "export type ReplicaDbJsonValue = null | boolean | number | string | Array<ReplicaDbJsonValue> | { [key: string]: ReplicaDbJsonValue };" + assert!(REPLICA_SCHEMA_BINDINGS_TYPES_TS.contains( + "export type ReplicaStoreJsonValue = null | boolean | number | string | Array<ReplicaStoreJsonValue> | { [key: string]: ReplicaStoreJsonValue };" )); assert!( - REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS + REPLICA_SCHEMA_BINDINGS_TYPES_TS .contains("export type IFarmFindOneResolve = ReplicaSchemaResult<Farm | null>;") ); assert!(actual.contains(&"ReplicaSchemaResult")); @@ -944,13 +940,13 @@ mod tests { assert!(actual.contains(&"ReplicaSchemaError")); assert!(trade_product_filter.contains("year?: bigint")); assert!(trade_product_filter.contains("qty_avail?: bigint")); - assert!(trade_product_partial.contains("year?: ReplicaDbJsonValue | null")); - assert!(trade_product_partial.contains("qty_avail?: ReplicaDbJsonValue | null")); + assert!(trade_product_partial.contains("year?: ReplicaStoreJsonValue | null")); + assert!(trade_product_partial.contains("qty_avail?: ReplicaStoreJsonValue | null")); } #[test] - fn replica_db_schema_generated_types_match_source_public_inventory() { - let actual = type_inventory(REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS) + fn replica_schema_generated_types_match_source_public_inventory() { + let actual = type_inventory(REPLICA_SCHEMA_BINDINGS_TYPES_TS) .into_iter() .collect::<BTreeSet<_>>(); let missing = source_public_schema_type_inventory() @@ -967,22 +963,22 @@ mod tests { #[test] fn trade_package_imports_source_owned_support_types() { assert!(TRADE_BINDINGS_TYPES_TS.contains("from \"@radroots/core-bindings\"")); - assert!(TRADE_BINDINGS_TYPES_TS.contains("from \"@radroots/events-bindings\"")); + assert!(TRADE_BINDINGS_TYPES_TS.contains("from \"@radroots/event-bindings\"")); let imports = imported_type_inventory(TRADE_BINDINGS_TYPES_TS); assert!( imports - .get("@radroots/events-bindings") + .get("@radroots/event-bindings") .is_some_and(|names| names.contains("RadrootsOrderEventType")) ); assert!( imports - .get("@radroots/events-bindings") + .get("@radroots/event-bindings") .is_some_and(|names| names.contains("RadrootsOrderEconomics")) ); assert!( imports - .get("@radroots/events-bindings") + .get("@radroots/event-bindings") .is_some_and(|names| names.contains("RadrootsOrderInventoryCommitment")) ); diff --git a/tools/sdk_xtask_import/src/output.rs b/tools/sdk_xtask_import/src/output.rs @@ -88,19 +88,15 @@ pub fn package_outputs() -> Result<Vec<PackageOutput>, String> { kinds_ts: None, }, PackageOutput { - spec: spec_by_key("events"), - types_ts: Some(TsSource::DtoRegistry(dto_roots::events_types_module()?)), + spec: spec_by_key("event"), + types_ts: Some(TsSource::DtoRegistry(dto_roots::event_types_module()?)), types_imports: Vec::new(), - constants_ts: Some(TsSource::Module( - radroots_events_bindings::constants_module(), - )), - kinds_ts: Some(TsSource::Module(radroots_events_bindings::kinds_module())), + constants_ts: Some(TsSource::Module(radroots_event_bindings::constants_module())), + kinds_ts: Some(TsSource::Module(radroots_event_bindings::kinds_module())), }, PackageOutput { - spec: spec_by_key("events_indexed"), - types_ts: Some(TsSource::DtoRegistry( - dto_roots::events_indexed_types_module()?, - )), + spec: spec_by_key("event_index"), + types_ts: Some(TsSource::DtoRegistry(dto_roots::event_index_types_module()?)), types_imports: Vec::new(), constants_ts: None, kinds_ts: None, @@ -115,9 +111,9 @@ pub fn package_outputs() -> Result<Vec<PackageOutput>, String> { kinds_ts: None, }, PackageOutput { - spec: spec_by_key("replica_db_schema"), + spec: spec_by_key("replica_schema"), types_ts: Some(TsSource::DtoRegistry( - dto_roots::replica_db_schema_types_module()?, + dto_roots::replica_schema_types_module()?, )), types_imports: Vec::new(), constants_ts: None, @@ -194,12 +190,12 @@ mod tests { const TRADE_BINDINGS_TYPES_TS: &str = include_str!("../../../packages/trade-bindings/src/generated/types.ts"); - const REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS: &str = - include_str!("../../../packages/replica-db-schema-bindings/src/generated/types.ts"); - const EVENTS_BINDINGS_CONSTANTS_TS: &str = - include_str!("../../../packages/events-bindings/src/generated/constants.ts"); - const EVENTS_BINDINGS_KINDS_TS: &str = - include_str!("../../../packages/events-bindings/src/generated/kinds.ts"); + const REPLICA_SCHEMA_BINDINGS_TYPES_TS: &str = + include_str!("../../../packages/replica-schema-bindings/src/generated/types.ts"); + const EVENT_BINDINGS_CONSTANTS_TS: &str = + include_str!("../../../packages/event-bindings/src/generated/constants.ts"); + const EVENT_BINDINGS_KINDS_TS: &str = + include_str!("../../../packages/event-bindings/src/generated/kinds.ts"); const IDENTITY_BINDINGS_CONSTANTS_TS: &str = include_str!("../../../packages/identity-bindings/src/generated/constants.ts"); @@ -236,10 +232,10 @@ mod tests { .map(|output| output.spec.package_name) .collect::<Vec<_>>(); assert!(package_names.contains(&"@radroots/core-bindings")); - assert!(package_names.contains(&"@radroots/events-bindings")); - assert!(package_names.contains(&"@radroots/events-indexed-bindings")); + assert!(package_names.contains(&"@radroots/event-bindings")); + assert!(package_names.contains(&"@radroots/event-index-bindings")); assert!(package_names.contains(&"@radroots/identity-bindings")); - assert!(package_names.contains(&"@radroots/replica-db-schema-bindings")); + assert!(package_names.contains(&"@radroots/replica-schema-bindings")); assert!(package_names.contains(&"@radroots/trade-bindings")); } @@ -316,12 +312,12 @@ mod tests { } #[test] - fn replica_db_schema_output_uses_dto_registry_and_matches_checked_in_types() { + fn replica_schema_output_uses_dto_registry_and_matches_checked_in_types() { let output = package_outputs() .expect("package outputs") .into_iter() - .find(|output| output.spec.key == "replica_db_schema") - .expect("replica_db_schema output"); + .find(|output| output.spec.key == "replica_schema") + .expect("replica_schema output"); assert!(matches!(output.types_ts, Some(TsSource::DtoRegistry(_)))); assert!(output.types_imports.is_empty()); @@ -332,7 +328,7 @@ mod tests { .find(|file| file.relative_path == "src/generated/types.ts") .expect("types file"); - assert_eq!(types.contents, REPLICA_DB_SCHEMA_BINDINGS_TYPES_TS); + assert_eq!(types.contents, REPLICA_SCHEMA_BINDINGS_TYPES_TS); } #[test] @@ -340,8 +336,8 @@ mod tests { let output = package_outputs() .expect("package outputs") .into_iter() - .find(|output| output.spec.key == "events") - .expect("events output"); + .find(|output| output.spec.key == "event") + .expect("event output"); assert!(matches!(output.constants_ts, Some(TsSource::Module(_)))); assert!(matches!(output.kinds_ts, Some(TsSource::Module(_)))); @@ -356,8 +352,8 @@ mod tests { .find(|file| file.relative_path == "src/generated/kinds.ts") .expect("kinds file"); - assert_eq!(constants.contents, EVENTS_BINDINGS_CONSTANTS_TS); - assert_eq!(kinds.contents, EVENTS_BINDINGS_KINDS_TS); + assert_eq!(constants.contents, EVENT_BINDINGS_CONSTANTS_TS); + assert_eq!(kinds.contents, EVENT_BINDINGS_KINDS_TS); } #[test] diff --git a/tools/sdk_xtask_import/src/package_matrix.rs b/tools/sdk_xtask_import/src/package_matrix.rs @@ -29,18 +29,18 @@ pub const PACKAGE_SPECS: [PackageSpec; 6] = [ package_dir: "packages/core-bindings", }, PackageSpec { - key: "events", - crate_name: "radroots_events_bindings", - crate_dir: "crates/events_bindings", - package_name: "@radroots/events-bindings", - package_dir: "packages/events-bindings", + key: "event", + crate_name: "radroots_event_bindings", + crate_dir: "crates/event_bindings", + package_name: "@radroots/event-bindings", + package_dir: "packages/event-bindings", }, PackageSpec { - key: "events_indexed", - crate_name: "radroots_events_indexed_bindings", - crate_dir: "crates/events_indexed_bindings", - package_name: "@radroots/events-indexed-bindings", - package_dir: "packages/events-indexed-bindings", + key: "event_index", + crate_name: "radroots_event_index_bindings", + crate_dir: "crates/event_index_bindings", + package_name: "@radroots/event-index-bindings", + package_dir: "packages/event-index-bindings", }, PackageSpec { key: "identity", @@ -50,11 +50,11 @@ pub const PACKAGE_SPECS: [PackageSpec; 6] = [ package_dir: "packages/identity-bindings", }, PackageSpec { - key: "replica_db_schema", - crate_name: "radroots_replica_db_schema_bindings", - crate_dir: "crates/replica_db_schema_bindings", - package_name: "@radroots/replica-db-schema-bindings", - package_dir: "packages/replica-db-schema-bindings", + key: "replica_schema", + crate_name: "radroots_replica_schema_bindings", + crate_dir: "crates/replica_schema_bindings", + package_name: "@radroots/replica-schema-bindings", + package_dir: "packages/replica-schema-bindings", }, PackageSpec { key: "trade", @@ -67,22 +67,22 @@ pub const PACKAGE_SPECS: [PackageSpec; 6] = [ pub const WASM_PACKAGE_SPECS: [WasmPackageSpec; 3] = [ WasmPackageSpec { - key: "events_codec", - crate_name: "radroots_events_codec_wasm", - crate_dir: "crates/events_codec_wasm", - package_name: "@radroots/events-codec-wasm", - package_dir: "packages/events-codec-wasm", - out_name: "radroots_events_codec_wasm", - out_dir: "../../packages/events-codec-wasm/dist", + key: "event_codec", + crate_name: "radroots_event_codec_wasm", + crate_dir: "crates/event_codec_wasm", + package_name: "@radroots/event-codec-wasm", + package_dir: "packages/event-codec-wasm", + out_name: "radroots_event_codec_wasm", + out_dir: "../../packages/event-codec-wasm/dist", }, WasmPackageSpec { - key: "replica_db", - crate_name: "radroots_replica_db_wasm", - crate_dir: "crates/replica_db_wasm", - package_name: "@radroots/replica-db-wasm", - package_dir: "packages/replica-db-wasm", - out_name: "radroots_replica_db_wasm", - out_dir: "../../packages/replica-db-wasm/dist", + key: "replica_store", + crate_name: "radroots_replica_store_wasm", + crate_dir: "crates/replica_store_wasm", + package_name: "@radroots/replica-store-wasm", + package_dir: "packages/replica-store-wasm", + out_name: "radroots_replica_store_wasm", + out_dir: "../../packages/replica-store-wasm/dist", }, WasmPackageSpec { key: "replica_sync", @@ -191,7 +191,7 @@ mod tests { assert!( package_specs() .iter() - .any(|spec| spec.package_name == "@radroots/replica-db-schema-bindings") + .any(|spec| spec.package_name == "@radroots/replica-schema-bindings") ); } @@ -200,7 +200,7 @@ mod tests { assert!( wasm_package_specs() .iter() - .any(|spec| spec.package_name == "@radroots/replica-db-wasm") + .any(|spec| spec.package_name == "@radroots/replica-store-wasm") ); } } diff --git a/tools/sdk_xtask_import/src/wasm.rs b/tools/sdk_xtask_import/src/wasm.rs @@ -219,7 +219,7 @@ fn selected_specs(args: &[String]) -> Result<Vec<WasmPackageSpec>, String> { } fn wasm_package_requires_c_compiler(spec: WasmPackageSpec) -> bool { - spec.key == "events_codec" + spec.key == "event_codec" } fn resolve_required_path_tool(name: &str) -> Result<PathBuf, String> { @@ -708,9 +708,9 @@ mod tests { #[test] fn selects_one_spec_by_key() { - let specs = selected_specs(&["--package".to_owned(), "replica_db".to_owned()]) - .expect("replica db spec"); - assert_eq!(specs[0].package_name, "@radroots/replica-db-wasm"); + let specs = selected_specs(&["--package".to_owned(), "replica_store".to_owned()]) + .expect("replica store spec"); + assert_eq!(specs[0].package_name, "@radroots/replica-store-wasm"); } #[test] @@ -957,7 +957,7 @@ channel = "1.92.0" } #[test] - fn events_codec_wasm_requires_c_compiler() { + fn event_codec_wasm_requires_c_compiler() { assert!(wasm_package_requires_c_compiler(wasm_package_specs()[0])); assert!(!wasm_package_requires_c_compiler(wasm_package_specs()[1])); } diff --git a/tools/sdk_xtask_import/src/wasm_declarations.rs b/tools/sdk_xtask_import/src/wasm_declarations.rs @@ -134,12 +134,12 @@ pub fn declaration_files(spec: WasmPackageSpec) -> Result<Vec<WasmDeclarationFil fn inventory(spec: WasmPackageSpec) -> Result<WasmDeclarationInventory, String> { match spec.key { - "events_codec" => Ok(WasmDeclarationInventory { - public_functions: EVENTS_CODEC_FUNCTIONS, - support_exports: EVENTS_CODEC_SUPPORT_EXPORTS, + "event_codec" => Ok(WasmDeclarationInventory { + public_functions: EVENT_CODEC_FUNCTIONS, + support_exports: EVENT_CODEC_SUPPORT_EXPORTS, }), - "replica_db" => Ok(WasmDeclarationInventory { - public_functions: REPLICA_DB_FUNCTIONS, + "replica_store" => Ok(WasmDeclarationInventory { + public_functions: REPLICA_STORE_FUNCTIONS, support_exports: SQL_WASM_SUPPORT_EXPORTS, }), "replica_sync" => Ok(WasmDeclarationInventory { @@ -353,7 +353,7 @@ fn promise_of(type_expr: TypeScriptType) -> TypeScriptType { TypeScriptType::generic("Promise", vec![type_expr]) } -const EVENTS_CODEC_FUNCTIONS: &[WasmPublicFunction] = &[ +const EVENT_CODEC_FUNCTIONS: &[WasmPublicFunction] = &[ public_function!("article_tags", Some("article_json"), String, 2, 4), public_function!("calendar_date_event_tags", Some("event_json"), String, 2, 4), public_function!("calendar_event_rsvp_tags", Some("rsvp_json"), String, 2, 4), @@ -442,7 +442,7 @@ const EVENTS_CODEC_FUNCTIONS: &[WasmPublicFunction] = &[ public_function!("contract_manifest_json", None, String, 0, 4), ]; -const EVENTS_CODEC_SUPPORT_EXPORTS: &[WasmSupportExport] = &[ +const EVENT_CODEC_SUPPORT_EXPORTS: &[WasmSupportExport] = &[ memory_export!(), table_export!("__wbindgen_externrefs"), number_function_export!("__wbindgen_malloc", 2), @@ -452,447 +452,513 @@ const EVENTS_CODEC_SUPPORT_EXPORTS: &[WasmSupportExport] = &[ void_function_export!("__wbindgen_start", 0), ]; -const REPLICA_DB_FUNCTIONS: &[WasmPublicFunction] = &[ - public_function!("replica_db_export_begin", None, Any, 0, 3), - public_function!("replica_db_export_finish", None, Void, 0, 2), - public_function!("replica_db_export_json", None, Any, 0, 3), - public_function!("replica_db_farm_create", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_farm_delete", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_farm_find_many", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_farm_find_one", Some("opts_json"), Any, 2, 3), +const REPLICA_STORE_FUNCTIONS: &[WasmPublicFunction] = &[ + public_function!("replica_store_export_begin", None, Any, 0, 3), + public_function!("replica_store_export_finish", None, Void, 0, 2), + public_function!("replica_store_export_json", None, Any, 0, 3), + public_function!("replica_store_farm_create", Some("opts_json"), Any, 2, 3), + public_function!("replica_store_farm_delete", Some("opts_json"), Any, 2, 3), + public_function!("replica_store_farm_find_many", Some("opts_json"), Any, 2, 3), + public_function!("replica_store_farm_find_one", Some("opts_json"), Any, 2, 3), + public_function!( + "replica_store_farm_gcs_location_create", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_gcs_location_delete", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_gcs_location_find_many", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_gcs_location_find_one", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_gcs_location_update", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_member_claim_create", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_member_claim_delete", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_member_claim_find_many", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_member_claim_find_one", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_member_claim_update", + Some("opts_json"), + Any, + 2, + 3 + ), + public_function!( + "replica_store_farm_member_create", + Some("opts_json"), + Any, + 2, + 3 + ), public_function!( - "replica_db_farm_gcs_location_create", + "replica_store_farm_member_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_gcs_location_delete", + "replica_store_farm_member_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_gcs_location_find_many", + "replica_store_farm_member_find_one", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_gcs_location_find_one", + "replica_store_farm_member_update", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_gcs_location_update", + "replica_store_farm_tag_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_claim_create", + "replica_store_farm_tag_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_claim_delete", + "replica_store_farm_tag_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_claim_find_many", + "replica_store_farm_tag_find_one", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_claim_find_one", + "replica_store_farm_tag_update", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_claim_update", + "replica_store_gcs_location_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_create", + "replica_store_gcs_location_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_delete", + "replica_store_gcs_location_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_find_many", + "replica_store_gcs_location_find_one", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_farm_member_find_one", + "replica_store_gcs_location_update", Some("opts_json"), Any, 2, 3 ), + public_function!("replica_store_import_json", Some("dump_json"), Void, 2, 2), public_function!( - "replica_db_farm_member_update", + "replica_store_log_error_create", Some("opts_json"), Any, 2, 3 ), - public_function!("replica_db_farm_tag_create", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_farm_tag_delete", Some("opts_json"), Any, 2, 3), public_function!( - "replica_db_farm_tag_find_many", + "replica_store_log_error_delete", Some("opts_json"), Any, 2, 3 ), - public_function!("replica_db_farm_tag_find_one", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_farm_tag_update", Some("opts_json"), Any, 2, 3), public_function!( - "replica_db_gcs_location_create", + "replica_store_log_error_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_gcs_location_delete", + "replica_store_log_error_find_one", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_gcs_location_find_many", + "replica_store_log_error_update", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_gcs_location_find_one", + "replica_store_media_image_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_gcs_location_update", + "replica_store_media_image_delete", Some("opts_json"), Any, 2, 3 ), - public_function!("replica_db_import_json", Some("dump_json"), Void, 2, 2), - public_function!("replica_db_log_error_create", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_log_error_delete", Some("opts_json"), Any, 2, 3), public_function!( - "replica_db_log_error_find_many", + "replica_store_media_image_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_log_error_find_one", + "replica_store_media_image_find_one", Some("opts_json"), Any, 2, 3 ), - public_function!("replica_db_log_error_update", Some("opts_json"), Any, 2, 3), public_function!( - "replica_db_media_image_create", + "replica_store_media_image_update", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_media_image_delete", + "replica_store_nostr_event_head_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_media_image_find_many", + "replica_store_nostr_event_head_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_media_image_find_one", + "replica_store_nostr_event_head_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_media_image_update", + "replica_store_nostr_event_head_find_one", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_event_head_create", + "replica_store_nostr_event_head_update", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_event_head_delete", + "replica_store_nostr_profile_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_event_head_find_many", + "replica_store_nostr_profile_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_event_head_find_one", + "replica_store_nostr_profile_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_event_head_update", + "replica_store_nostr_profile_find_one", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_profile_create", + "replica_store_nostr_profile_relay_set", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_profile_delete", + "replica_store_nostr_profile_relay_unset", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_profile_find_many", + "replica_store_nostr_profile_update", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_profile_find_one", + "replica_store_nostr_relay_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_profile_relay_set", + "replica_store_nostr_relay_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_profile_relay_unset", + "replica_store_nostr_relay_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_profile_update", + "replica_store_nostr_relay_find_one", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_relay_create", + "replica_store_nostr_relay_update", Some("opts_json"), Any, 2, 3 ), + public_function!("replica_store_plot_create", Some("opts_json"), Any, 2, 3), + public_function!("replica_store_plot_delete", Some("opts_json"), Any, 2, 3), + public_function!("replica_store_plot_find_many", Some("opts_json"), Any, 2, 3), + public_function!("replica_store_plot_find_one", Some("opts_json"), Any, 2, 3), public_function!( - "replica_db_nostr_relay_delete", + "replica_store_plot_gcs_location_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_relay_find_many", + "replica_store_plot_gcs_location_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_relay_find_one", + "replica_store_plot_gcs_location_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_nostr_relay_update", + "replica_store_plot_gcs_location_find_one", Some("opts_json"), Any, 2, 3 ), - public_function!("replica_db_plot_create", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_plot_delete", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_plot_find_many", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_plot_find_one", Some("opts_json"), Any, 2, 3), public_function!( - "replica_db_plot_gcs_location_create", + "replica_store_plot_gcs_location_update", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_plot_gcs_location_delete", + "replica_store_plot_tag_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_plot_gcs_location_find_many", + "replica_store_plot_tag_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_plot_gcs_location_find_one", + "replica_store_plot_tag_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_plot_gcs_location_update", + "replica_store_plot_tag_find_one", Some("opts_json"), Any, 2, 3 ), - public_function!("replica_db_plot_tag_create", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_plot_tag_delete", Some("opts_json"), Any, 2, 3), public_function!( - "replica_db_plot_tag_find_many", + "replica_store_plot_tag_update", Some("opts_json"), Any, 2, 3 ), - public_function!("replica_db_plot_tag_find_one", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_plot_tag_update", Some("opts_json"), Any, 2, 3), - public_function!("replica_db_reset_database", None, Void, 0, 2), - public_function!("replica_db_run_migrations", None, Void, 0, 2), + public_function!("replica_store_reset_database", None, Void, 0, 2), + public_function!("replica_store_run_migrations", None, Void, 0, 2), public_function!( - "replica_db_trade_product_create", + "replica_store_trade_product_create", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_trade_product_delete", + "replica_store_trade_product_delete", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_trade_product_find_many", + "replica_store_trade_product_find_many", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_trade_product_find_one", + "replica_store_trade_product_find_one", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_trade_product_location_set", + "replica_store_trade_product_location_set", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_trade_product_location_unset", + "replica_store_trade_product_location_unset", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_trade_product_media_set", + "replica_store_trade_product_media_set", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_trade_product_media_unset", + "replica_store_trade_product_media_unset", Some("opts_json"), Any, 2, 3 ), public_function!( - "replica_db_trade_product_update", + "replica_store_trade_product_update", Some("opts_json"), Any, 2, @@ -948,7 +1014,7 @@ mod tests { #[test] fn generated_declarations_include_public_wasm_entrypoints() { let specs = wasm_package_specs(); - let events = declaration_files(specs[0]).expect("events declarations"); + let events = declaration_files(specs[0]).expect("event declarations"); assert!(events[0].contents.contains("export function listing_tags")); assert!( events[1] @@ -956,16 +1022,16 @@ mod tests { .contains("export declare const listing_tags") ); - let replica_db = declaration_files(specs[1]).expect("replica db declarations"); + let replica_store = declaration_files(specs[1]).expect("replica store declarations"); assert!( - replica_db[0] + replica_store[0] .contents - .contains("export function replica_db_farm_create") + .contains("export function replica_store_farm_create") ); assert!( - replica_db[1] + replica_store[1] .contents - .contains("export declare const replica_db_farm_create") + .contains("export declare const replica_store_farm_create") ); let replica_sync = declaration_files(specs[2]).expect("replica sync declarations");