tangle


git clone https://radroots.dev/git/tangle.git
Log | Files | Refs | README | LICENSE

commit 67fc7598bdc72c50c1ba7db7ccef327918692b90
parent b473e4f6b4cf26434239f65481505eb3ddee2dfd
Author: triesap <tyson@radroots.org>
Date:   Sat,  6 Jun 2026 03:26:05 -0700

migrations: add reaction schemas

Diffstat:
Mcrates/tangle_store_surreal/src/lib.rs | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 98 insertions(+), 0 deletions(-)

diff --git a/crates/tangle_store_surreal/src/lib.rs b/crates/tangle_store_surreal/src/lib.rs @@ -307,6 +307,7 @@ pub fn base_migration_plan() -> SurrealMigrationPlan { search_document_schema(), policy_schemas(), comment_projection_schema(), + reaction_projection_schema(), ]) .expect("base migration plan is strictly ordered") } @@ -674,6 +675,46 @@ DEFINE INDEX IF NOT EXISTS comment_projection_author_created ON TABLE comment_pr .expect("comment projection schema is valid") } +pub fn reaction_projection_schema() -> SurrealMigration { + SurrealMigration::new( + "0012_reaction_projection", + r#" +DEFINE TABLE IF NOT EXISTS reaction_projection SCHEMAFULL; +DEFINE FIELD IF NOT EXISTS reaction_id ON TABLE reaction_projection TYPE string; +DEFINE FIELD IF NOT EXISTS event_id ON TABLE reaction_projection TYPE string; +DEFINE FIELD IF NOT EXISTS pubkey ON TABLE reaction_projection TYPE string; +DEFINE FIELD IF NOT EXISTS created_at ON TABLE reaction_projection TYPE int; +DEFINE FIELD IF NOT EXISTS content ON TABLE reaction_projection TYPE string; +DEFINE FIELD IF NOT EXISTS value_type ON TABLE reaction_projection TYPE string; +DEFINE FIELD IF NOT EXISTS value ON TABLE reaction_projection TYPE string; +DEFINE FIELD IF NOT EXISTS target_event_id ON TABLE reaction_projection TYPE string; +DEFINE FIELD IF NOT EXISTS target_pubkey ON TABLE reaction_projection TYPE option<string>; +DEFINE FIELD IF NOT EXISTS target_address ON TABLE reaction_projection TYPE option<string>; +DEFINE FIELD IF NOT EXISTS target_kind ON TABLE reaction_projection TYPE option<string>; +DEFINE FIELD IF NOT EXISTS hidden ON TABLE reaction_projection TYPE bool DEFAULT false; +DEFINE FIELD IF NOT EXISTS deleted ON TABLE reaction_projection TYPE bool DEFAULT false; +DEFINE FIELD IF NOT EXISTS projected_at ON TABLE reaction_projection TYPE int; +DEFINE INDEX IF NOT EXISTS reaction_projection_event_uid ON TABLE reaction_projection COLUMNS event_id UNIQUE; +DEFINE INDEX IF NOT EXISTS reaction_projection_target_created ON TABLE reaction_projection COLUMNS target_event_id, created_at, event_id; +DEFINE INDEX IF NOT EXISTS reaction_projection_author_created ON TABLE reaction_projection COLUMNS pubkey, created_at, event_id; +DEFINE INDEX IF NOT EXISTS reaction_projection_target_kind ON TABLE reaction_projection COLUMNS target_kind, target_event_id; + +DEFINE TABLE IF NOT EXISTS reaction_count SCHEMAFULL; +DEFINE FIELD IF NOT EXISTS target_event_id ON TABLE reaction_count TYPE string; +DEFINE FIELD IF NOT EXISTS target_kind ON TABLE reaction_count TYPE option<string>; +DEFINE FIELD IF NOT EXISTS like_count ON TABLE reaction_count TYPE int DEFAULT 0; +DEFINE FIELD IF NOT EXISTS dislike_count ON TABLE reaction_count TYPE int DEFAULT 0; +DEFINE FIELD IF NOT EXISTS emoji_count ON TABLE reaction_count TYPE int DEFAULT 0; +DEFINE FIELD IF NOT EXISTS text_count ON TABLE reaction_count TYPE int DEFAULT 0; +DEFINE FIELD IF NOT EXISTS total_count ON TABLE reaction_count TYPE int DEFAULT 0; +DEFINE FIELD IF NOT EXISTS updated_at ON TABLE reaction_count TYPE int; +DEFINE INDEX IF NOT EXISTS reaction_count_target_uid ON TABLE reaction_count COLUMNS target_event_id UNIQUE; +DEFINE INDEX IF NOT EXISTS reaction_count_kind_target ON TABLE reaction_count COLUMNS target_kind, target_event_id; +"#, + ) + .expect("reaction projection schema is valid") +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct AppliedMigration { name: String, @@ -3654,6 +3695,63 @@ mod tests { } #[tokio::test] + async fn reaction_projection_schema_defines_reaction_and_count_tables() { + let store = memory_store().await; + store + .apply_plan(&base_migration_plan()) + .await + .expect("apply plan"); + let projection = store + .table_info("reaction_projection") + .await + .expect("projection info"); + let count = store + .table_info("reaction_count") + .await + .expect("count info"); + + for expected in [ + "reaction_id", + "event_id", + "pubkey", + "created_at", + "content", + "value_type", + "value", + "target_event_id", + "target_pubkey", + "target_address", + "target_kind", + "hidden", + "deleted", + "projected_at", + "reaction_projection_event_uid", + "reaction_projection_target_created", + "reaction_projection_author_created", + "reaction_projection_target_kind", + ] { + assert!( + projection.contains(expected), + "missing {expected} in {projection}" + ); + } + for expected in [ + "target_event_id", + "target_kind", + "like_count", + "dislike_count", + "emoji_count", + "text_count", + "total_count", + "updated_at", + "reaction_count_target_uid", + "reaction_count_kind_target", + ] { + assert!(count.contains(expected), "missing {expected} in {count}"); + } + } + + #[tokio::test] async fn listing_current_schema_defines_marketplace_projection_table() { let store = memory_store().await; store