region_scripted_paths.rs (27478B)
1 use std::collections::VecDeque; 2 use std::sync::Mutex; 3 4 use radroots_replica_schema::ReplicaSchemaError; 5 use radroots_replica_schema::farm::{ 6 IFarmCreate, IFarmDelete, IFarmFindMany, IFarmFindOne, IFarmUpdate, 7 }; 8 use radroots_replica_schema::farm_gcs_location::{ 9 IFarmGcsLocationCreate, IFarmGcsLocationDelete, IFarmGcsLocationFindMany, 10 IFarmGcsLocationFindOne, IFarmGcsLocationUpdate, 11 }; 12 use radroots_replica_schema::farm_member::{ 13 IFarmMemberCreate, IFarmMemberDelete, IFarmMemberFindMany, IFarmMemberFindOne, 14 IFarmMemberUpdate, 15 }; 16 use radroots_replica_schema::farm_member_claim::{ 17 IFarmMemberClaimCreate, IFarmMemberClaimDelete, IFarmMemberClaimFindMany, 18 IFarmMemberClaimFindOne, IFarmMemberClaimUpdate, 19 }; 20 use radroots_replica_schema::farm_tag::{ 21 IFarmTagCreate, IFarmTagDelete, IFarmTagFindMany, IFarmTagFindOne, IFarmTagUpdate, 22 }; 23 use radroots_replica_schema::gcs_location::{ 24 GcsLocationFarmArgs, GcsLocationFindManyRel, GcsLocationPlotArgs, GcsLocationTradeProductArgs, 25 IGcsLocationCreate, IGcsLocationDelete, IGcsLocationFindMany, IGcsLocationFindOne, 26 IGcsLocationFindOneRelArgs, IGcsLocationUpdate, 27 }; 28 use radroots_replica_schema::log_error::{ 29 ILogErrorCreate, ILogErrorDelete, ILogErrorFindMany, ILogErrorFindOne, ILogErrorUpdate, 30 }; 31 use radroots_replica_schema::media_image::{ 32 IMediaImageCreate, IMediaImageDelete, IMediaImageFindMany, IMediaImageFindOne, 33 IMediaImageFindOneRelArgs, IMediaImageUpdate, MediaImageFindManyRel, 34 MediaImageTradeProductArgs, 35 }; 36 use radroots_replica_schema::nostr_event_head::{ 37 INostrEventHeadCreate, INostrEventHeadDelete, INostrEventHeadFindMany, INostrEventHeadFindOne, 38 INostrEventHeadUpdate, 39 }; 40 use radroots_replica_schema::nostr_profile::{ 41 INostrProfileCreate, INostrProfileDelete, INostrProfileFindMany, INostrProfileFindOne, 42 INostrProfileFindOneRelArgs, INostrProfileUpdate, NostrProfileFindManyRel, 43 NostrProfileRelayArgs, 44 }; 45 use radroots_replica_schema::nostr_relay::{ 46 INostrRelayCreate, INostrRelayDelete, INostrRelayFindMany, INostrRelayFindOne, 47 INostrRelayFindOneRelArgs, INostrRelayUpdate, NostrRelayFindManyRel, NostrRelayProfileArgs, 48 }; 49 use radroots_replica_schema::plot::{ 50 IPlotCreate, IPlotDelete, IPlotFindMany, IPlotFindOne, IPlotUpdate, 51 }; 52 use radroots_replica_schema::plot_gcs_location::{ 53 IPlotGcsLocationCreate, IPlotGcsLocationDelete, IPlotGcsLocationFindMany, 54 IPlotGcsLocationFindOne, IPlotGcsLocationUpdate, 55 }; 56 use radroots_replica_schema::plot_tag::{ 57 IPlotTagCreate, IPlotTagDelete, IPlotTagFindMany, IPlotTagFindOne, IPlotTagUpdate, 58 }; 59 use radroots_replica_schema::trade_product::{ 60 ITradeProductCreate, ITradeProductFindMany, ITradeProductFindOne, ITradeProductUpdate, 61 }; 62 use radroots_replica_store::{ExecOutcome, ReplicaSql, SqlError, SqlExecutor}; 63 use serde::de::DeserializeOwned; 64 use serde_json::json; 65 66 struct ScriptedExecutor { 67 exec_results: Mutex<VecDeque<Result<ExecOutcome, SqlError>>>, 68 query_results: Mutex<VecDeque<Result<String, SqlError>>>, 69 begin_results: Mutex<VecDeque<Result<(), SqlError>>>, 70 commit_results: Mutex<VecDeque<Result<(), SqlError>>>, 71 rollback_results: Mutex<VecDeque<Result<(), SqlError>>>, 72 } 73 74 impl ScriptedExecutor { 75 fn new( 76 exec_results: Vec<Result<ExecOutcome, SqlError>>, 77 query_results: Vec<Result<String, SqlError>>, 78 ) -> Self { 79 Self { 80 exec_results: Mutex::new(VecDeque::from(exec_results)), 81 query_results: Mutex::new(VecDeque::from(query_results)), 82 begin_results: Mutex::new(VecDeque::new()), 83 commit_results: Mutex::new(VecDeque::new()), 84 rollback_results: Mutex::new(VecDeque::new()), 85 } 86 } 87 } 88 89 impl SqlExecutor for ScriptedExecutor { 90 fn exec(&self, _sql: &str, _params_json: &str) -> Result<ExecOutcome, SqlError> { 91 if let Some(result) = self 92 .exec_results 93 .lock() 94 .expect("lock exec queue") 95 .pop_front() 96 { 97 result 98 } else { 99 Ok(ExecOutcome { 100 changes: 1, 101 last_insert_id: 1, 102 }) 103 } 104 } 105 106 fn query_raw(&self, _sql: &str, _params_json: &str) -> Result<String, SqlError> { 107 if let Some(result) = self 108 .query_results 109 .lock() 110 .expect("lock query queue") 111 .pop_front() 112 { 113 result 114 } else { 115 Ok(String::from("[]")) 116 } 117 } 118 119 fn begin(&self) -> Result<(), SqlError> { 120 if let Some(result) = self 121 .begin_results 122 .lock() 123 .expect("lock begin queue") 124 .pop_front() 125 { 126 result 127 } else { 128 Ok(()) 129 } 130 } 131 132 fn commit(&self) -> Result<(), SqlError> { 133 if let Some(result) = self 134 .commit_results 135 .lock() 136 .expect("lock commit queue") 137 .pop_front() 138 { 139 result 140 } else { 141 Ok(()) 142 } 143 } 144 145 fn rollback(&self) -> Result<(), SqlError> { 146 if let Some(result) = self 147 .rollback_results 148 .lock() 149 .expect("lock rollback queue") 150 .pop_front() 151 { 152 result 153 } else { 154 Ok(()) 155 } 156 } 157 } 158 159 fn parse_json<T: DeserializeOwned>(value: serde_json::Value) -> T { 160 serde_json::from_value(value).expect("valid test payload") 161 } 162 163 fn hex64(ch: char) -> String { 164 std::iter::repeat_n(ch, 64).collect() 165 } 166 167 fn err_query() -> Result<String, SqlError> { 168 Err(SqlError::InvalidQuery(String::from("forced query error"))) 169 } 170 171 fn bad_json() -> Result<String, SqlError> { 172 Ok(String::from("{")) 173 } 174 175 fn ok_rows() -> Result<String, SqlError> { 176 Ok(String::from("[]")) 177 } 178 179 fn ok_exec() -> Result<ExecOutcome, SqlError> { 180 Ok(ExecOutcome { 181 changes: 1, 182 last_insert_id: 1, 183 }) 184 } 185 186 fn db_with_scripts( 187 exec_results: Vec<Result<ExecOutcome, SqlError>>, 188 query_results: Vec<Result<String, SqlError>>, 189 ) -> ReplicaSql<ScriptedExecutor> { 190 ReplicaSql::new(ScriptedExecutor::new(exec_results, query_results)) 191 } 192 193 fn assert_replica_schema_error_code<T>( 194 result: Result<T, ReplicaSchemaError<SqlError>>, 195 code: &str, 196 ) { 197 let err = match result { 198 Ok(_) => panic!("expected ierror"), 199 Err(err) => err, 200 }; 201 assert_eq!(err.error.code(), code); 202 } 203 204 macro_rules! assert_secondary_model_paths { 205 ( 206 $test_name:ident, 207 $create_ty:ty, $create_json:expr, $create_call:ident, 208 $find_many_ty:ty, $find_many_json:expr, $find_many_call:ident, 209 $find_one_ty:ty, $find_one_json:expr, $find_one_call:ident, 210 $update_ty:ty, $update_id_json:expr, $update_lookup_json:expr, $update_call:ident, 211 $delete_ty:ty, $delete_lookup_json:expr, $delete_call:ident 212 ) => { 213 #[test] 214 fn $test_name() { 215 let create_opts: $create_ty = parse_json($create_json); 216 217 let db = db_with_scripts(vec![ok_exec()], vec![err_query()]); 218 assert_replica_schema_error_code(db.$create_call(&create_opts), "ERR_INVALID_QUERY"); 219 220 let db = db_with_scripts(vec![ok_exec()], vec![ok_rows()]); 221 assert_replica_schema_error_code(db.$create_call(&create_opts), "ERR_NOT_FOUND"); 222 223 let find_many_opts: $find_many_ty = parse_json($find_many_json); 224 let db = db_with_scripts(vec![], vec![bad_json()]); 225 assert_replica_schema_error_code( 226 db.$find_many_call(&find_many_opts), 227 "ERR_SERIALIZATION", 228 ); 229 230 let find_one_opts: $find_one_ty = parse_json($find_one_json); 231 let db = db_with_scripts(vec![], vec![bad_json()]); 232 assert_replica_schema_error_code( 233 db.$find_one_call(&find_one_opts), 234 "ERR_SERIALIZATION", 235 ); 236 237 let update_id_opts: $update_ty = parse_json($update_id_json); 238 let db = db_with_scripts(vec![ok_exec()], vec![err_query()]); 239 assert_replica_schema_error_code(db.$update_call(&update_id_opts), "ERR_INVALID_QUERY"); 240 241 let db = db_with_scripts(vec![ok_exec()], vec![bad_json()]); 242 assert_replica_schema_error_code(db.$update_call(&update_id_opts), "ERR_SERIALIZATION"); 243 244 let update_lookup_opts: $update_ty = parse_json($update_lookup_json); 245 let db = db_with_scripts(vec![], vec![err_query()]); 246 assert_replica_schema_error_code( 247 db.$update_call(&update_lookup_opts), 248 "ERR_INVALID_QUERY", 249 ); 250 251 let delete_lookup_opts: $delete_ty = parse_json($delete_lookup_json); 252 let db = db_with_scripts(vec![], vec![err_query()]); 253 assert_replica_schema_error_code( 254 db.$delete_call(&delete_lookup_opts), 255 "ERR_INVALID_QUERY", 256 ); 257 } 258 }; 259 } 260 261 macro_rules! assert_rel_model_paths { 262 ( 263 $test_name:ident, 264 $create_ty:ty, $create_json:expr, $create_call:ident, 265 $find_many_ty:ty, $find_many_filter_json:expr, $find_many_rel_expr:expr, $find_many_call:ident, 266 $find_one_ty:ty, $find_one_on_json:expr, $find_one_rel_expr:expr, $find_one_call:ident, 267 $update_ty:ty, $update_id_json:expr, $update_lookup_json:expr, $update_call:ident, 268 $delete_ty:ty, $delete_lookup_json:expr, $delete_rel_expr:expr, $delete_call:ident 269 ) => { 270 #[test] 271 fn $test_name() { 272 let create_opts: $create_ty = parse_json($create_json); 273 274 let db = db_with_scripts(vec![ok_exec()], vec![err_query()]); 275 assert_replica_schema_error_code(db.$create_call(&create_opts), "ERR_INVALID_QUERY"); 276 277 let db = db_with_scripts(vec![ok_exec()], vec![ok_rows()]); 278 assert_replica_schema_error_code(db.$create_call(&create_opts), "ERR_NOT_FOUND"); 279 280 let find_many_filter_opts: $find_many_ty = parse_json($find_many_filter_json); 281 let db = db_with_scripts(vec![], vec![bad_json()]); 282 assert_replica_schema_error_code( 283 db.$find_many_call(&find_many_filter_opts), 284 "ERR_SERIALIZATION", 285 ); 286 287 let find_many_rel_opts: $find_many_ty = $find_many_rel_expr; 288 let db = db_with_scripts(vec![], vec![bad_json()]); 289 assert_replica_schema_error_code( 290 db.$find_many_call(&find_many_rel_opts), 291 "ERR_SERIALIZATION", 292 ); 293 294 let find_many_rel_opts: $find_many_ty = $find_many_rel_expr; 295 let db = db_with_scripts(vec![], vec![err_query()]); 296 assert_replica_schema_error_code( 297 db.$find_many_call(&find_many_rel_opts), 298 "ERR_INVALID_QUERY", 299 ); 300 301 let find_one_on_opts: $find_one_ty = parse_json($find_one_on_json); 302 let db = db_with_scripts(vec![], vec![bad_json()]); 303 assert_replica_schema_error_code( 304 db.$find_one_call(&find_one_on_opts), 305 "ERR_SERIALIZATION", 306 ); 307 308 let find_one_rel_opts: $find_one_ty = $find_one_rel_expr; 309 let db = db_with_scripts(vec![], vec![bad_json()]); 310 assert_replica_schema_error_code( 311 db.$find_one_call(&find_one_rel_opts), 312 "ERR_SERIALIZATION", 313 ); 314 315 let update_id_opts: $update_ty = parse_json($update_id_json); 316 let db = db_with_scripts(vec![ok_exec()], vec![err_query()]); 317 assert_replica_schema_error_code(db.$update_call(&update_id_opts), "ERR_INVALID_QUERY"); 318 319 let db = db_with_scripts(vec![ok_exec()], vec![bad_json()]); 320 assert_replica_schema_error_code(db.$update_call(&update_id_opts), "ERR_SERIALIZATION"); 321 322 let update_lookup_opts: $update_ty = parse_json($update_lookup_json); 323 let db = db_with_scripts(vec![], vec![err_query()]); 324 assert_replica_schema_error_code( 325 db.$update_call(&update_lookup_opts), 326 "ERR_INVALID_QUERY", 327 ); 328 329 let delete_lookup_opts: $delete_ty = parse_json($delete_lookup_json); 330 let db = db_with_scripts(vec![], vec![err_query()]); 331 assert_replica_schema_error_code( 332 db.$delete_call(&delete_lookup_opts), 333 "ERR_INVALID_QUERY", 334 ); 335 336 let delete_rel_opts: $delete_ty = $delete_rel_expr; 337 let db = db_with_scripts(vec![], vec![err_query()]); 338 assert_replica_schema_error_code( 339 db.$delete_call(&delete_rel_opts), 340 "ERR_INVALID_QUERY", 341 ); 342 } 343 }; 344 } 345 346 macro_rules! assert_trade_product_paths { 347 ( 348 $test_name:ident, 349 $create_ty:ty, $create_json:expr, $create_call:ident, 350 $find_many_ty:ty, $find_many_json:expr, $find_many_call:ident, 351 $find_one_ty:ty, $find_one_json:expr, $find_one_call:ident, 352 $update_ty:ty, $update_json:expr, $update_call:ident 353 ) => { 354 #[test] 355 fn $test_name() { 356 let create_opts: $create_ty = parse_json($create_json); 357 358 let db = db_with_scripts(vec![ok_exec()], vec![err_query()]); 359 assert_replica_schema_error_code(db.$create_call(&create_opts), "ERR_INVALID_QUERY"); 360 361 let db = db_with_scripts(vec![ok_exec()], vec![ok_rows()]); 362 assert_replica_schema_error_code(db.$create_call(&create_opts), "ERR_NOT_FOUND"); 363 364 let find_many_opts: $find_many_ty = parse_json($find_many_json); 365 let db = db_with_scripts(vec![], vec![bad_json()]); 366 assert_replica_schema_error_code( 367 db.$find_many_call(&find_many_opts), 368 "ERR_SERIALIZATION", 369 ); 370 371 let find_one_opts: $find_one_ty = parse_json($find_one_json); 372 let db = db_with_scripts(vec![], vec![bad_json()]); 373 assert_replica_schema_error_code( 374 db.$find_one_call(&find_one_opts), 375 "ERR_SERIALIZATION", 376 ); 377 378 let update_opts: $update_ty = parse_json($update_json); 379 let db = db_with_scripts(vec![ok_exec()], vec![err_query()]); 380 assert_replica_schema_error_code(db.$update_call(&update_opts), "ERR_INVALID_QUERY"); 381 382 let db = db_with_scripts(vec![ok_exec()], vec![bad_json()]); 383 assert_replica_schema_error_code(db.$update_call(&update_opts), "ERR_SERIALIZATION"); 384 } 385 }; 386 } 387 388 assert_secondary_model_paths!( 389 farm_scripted_region_paths, 390 IFarmCreate, 391 json!({ "d_tag": "farm-a", "pubkey": hex64('a'), "name": "farm a" }), 392 farm_create, 393 IFarmFindMany, 394 json!({ "filter": { "id": "id-1" } }), 395 farm_find_many, 396 IFarmFindOne, 397 json!({ "on": { "id": "id-1" } }), 398 farm_find_one, 399 IFarmUpdate, 400 json!({ "on": { "id": "id-1" }, "fields": { "name": "farm z" } }), 401 json!({ "on": { "d_tag": "farm-a" }, "fields": { "name": "farm y" } }), 402 farm_update, 403 IFarmDelete, 404 json!({ "on": { "d_tag": "farm-a" } }), 405 farm_delete 406 ); 407 408 assert_secondary_model_paths!( 409 plot_scripted_region_paths, 410 IPlotCreate, 411 json!({ "d_tag": "plot-a", "farm_id": "farm-1", "name": "plot a" }), 412 plot_create, 413 IPlotFindMany, 414 json!({ "filter": { "id": "id-1" } }), 415 plot_find_many, 416 IPlotFindOne, 417 json!({ "on": { "id": "id-1" } }), 418 plot_find_one, 419 IPlotUpdate, 420 json!({ "on": { "id": "id-1" }, "fields": { "name": "plot z" } }), 421 json!({ "on": { "d_tag": "plot-a" }, "fields": { "name": "plot y" } }), 422 plot_update, 423 IPlotDelete, 424 json!({ "on": { "d_tag": "plot-a" } }), 425 plot_delete 426 ); 427 428 assert_secondary_model_paths!( 429 farm_gcs_location_scripted_region_paths, 430 IFarmGcsLocationCreate, 431 json!({ "farm_id": "farm-1", "gcs_location_id": "gcs-1", "role": "primary" }), 432 farm_gcs_location_create, 433 IFarmGcsLocationFindMany, 434 json!({ "filter": { "id": "id-1" } }), 435 farm_gcs_location_find_many, 436 IFarmGcsLocationFindOne, 437 json!({ "on": { "id": "id-1" } }), 438 farm_gcs_location_find_one, 439 IFarmGcsLocationUpdate, 440 json!({ "on": { "id": "id-1" }, "fields": { "role": "z" } }), 441 json!({ "on": { "farm_id": "farm-1" }, "fields": { "role": "y" } }), 442 farm_gcs_location_update, 443 IFarmGcsLocationDelete, 444 json!({ "on": { "farm_id": "farm-1" } }), 445 farm_gcs_location_delete 446 ); 447 448 assert_secondary_model_paths!( 449 plot_gcs_location_scripted_region_paths, 450 IPlotGcsLocationCreate, 451 json!({ "plot_id": "plot-1", "gcs_location_id": "gcs-1", "role": "primary" }), 452 plot_gcs_location_create, 453 IPlotGcsLocationFindMany, 454 json!({ "filter": { "id": "id-1" } }), 455 plot_gcs_location_find_many, 456 IPlotGcsLocationFindOne, 457 json!({ "on": { "id": "id-1" } }), 458 plot_gcs_location_find_one, 459 IPlotGcsLocationUpdate, 460 json!({ "on": { "id": "id-1" }, "fields": { "role": "z" } }), 461 json!({ "on": { "plot_id": "plot-1" }, "fields": { "role": "y" } }), 462 plot_gcs_location_update, 463 IPlotGcsLocationDelete, 464 json!({ "on": { "plot_id": "plot-1" } }), 465 plot_gcs_location_delete 466 ); 467 468 assert_secondary_model_paths!( 469 farm_tag_scripted_region_paths, 470 IFarmTagCreate, 471 json!({ "farm_id": "farm-1", "tag": "organic" }), 472 farm_tag_create, 473 IFarmTagFindMany, 474 json!({ "filter": { "id": "id-1" } }), 475 farm_tag_find_many, 476 IFarmTagFindOne, 477 json!({ "on": { "id": "id-1" } }), 478 farm_tag_find_one, 479 IFarmTagUpdate, 480 json!({ "on": { "id": "id-1" }, "fields": { "tag": "z" } }), 481 json!({ "on": { "farm_id": "farm-1" }, "fields": { "tag": "y" } }), 482 farm_tag_update, 483 IFarmTagDelete, 484 json!({ "on": { "farm_id": "farm-1" } }), 485 farm_tag_delete 486 ); 487 488 assert_secondary_model_paths!( 489 plot_tag_scripted_region_paths, 490 IPlotTagCreate, 491 json!({ "plot_id": "plot-1", "tag": "north" }), 492 plot_tag_create, 493 IPlotTagFindMany, 494 json!({ "filter": { "id": "id-1" } }), 495 plot_tag_find_many, 496 IPlotTagFindOne, 497 json!({ "on": { "id": "id-1" } }), 498 plot_tag_find_one, 499 IPlotTagUpdate, 500 json!({ "on": { "id": "id-1" }, "fields": { "tag": "z" } }), 501 json!({ "on": { "plot_id": "plot-1" }, "fields": { "tag": "y" } }), 502 plot_tag_update, 503 IPlotTagDelete, 504 json!({ "on": { "plot_id": "plot-1" } }), 505 plot_tag_delete 506 ); 507 508 assert_secondary_model_paths!( 509 farm_member_scripted_region_paths, 510 IFarmMemberCreate, 511 json!({ "farm_id": "farm-1", "member_pubkey": hex64('b'), "role": "owner" }), 512 farm_member_create, 513 IFarmMemberFindMany, 514 json!({ "filter": { "id": "id-1" } }), 515 farm_member_find_many, 516 IFarmMemberFindOne, 517 json!({ "on": { "id": "id-1" } }), 518 farm_member_find_one, 519 IFarmMemberUpdate, 520 json!({ "on": { "id": "id-1" }, "fields": { "role": "z" } }), 521 json!({ "on": { "member_pubkey": hex64('b') }, "fields": { "role": "y" } }), 522 farm_member_update, 523 IFarmMemberDelete, 524 json!({ "on": { "member_pubkey": hex64('b') } }), 525 farm_member_delete 526 ); 527 528 assert_secondary_model_paths!( 529 farm_member_claim_scripted_region_paths, 530 IFarmMemberClaimCreate, 531 json!({ "member_pubkey": hex64('b'), "farm_pubkey": hex64('a') }), 532 farm_member_claim_create, 533 IFarmMemberClaimFindMany, 534 json!({ "filter": { "id": "id-1" } }), 535 farm_member_claim_find_many, 536 IFarmMemberClaimFindOne, 537 json!({ "on": { "id": "id-1" } }), 538 farm_member_claim_find_one, 539 IFarmMemberClaimUpdate, 540 json!({ "on": { "id": "id-1" }, "fields": { "farm_pubkey": hex64('c') } }), 541 json!({ "on": { "member_pubkey": hex64('b') }, "fields": { "farm_pubkey": hex64('d') } }), 542 farm_member_claim_update, 543 IFarmMemberClaimDelete, 544 json!({ "on": { "member_pubkey": hex64('b') } }), 545 farm_member_claim_delete 546 ); 547 548 assert_secondary_model_paths!( 549 log_error_scripted_region_paths, 550 ILogErrorCreate, 551 json!({ 552 "error": "panic", 553 "message": "boom", 554 "app_system": "studio", 555 "app_version": "1.0.0", 556 "nostr_pubkey": hex64('c') 557 }), 558 log_error_create, 559 ILogErrorFindMany, 560 json!({ "filter": { "id": "id-1" } }), 561 log_error_find_many, 562 ILogErrorFindOne, 563 json!({ "on": { "id": "id-1" } }), 564 log_error_find_one, 565 ILogErrorUpdate, 566 json!({ "on": { "id": "id-1" }, "fields": { "message": "z" } }), 567 json!({ "on": { "nostr_pubkey": hex64('c') }, "fields": { "message": "y" } }), 568 log_error_update, 569 ILogErrorDelete, 570 json!({ "on": { "nostr_pubkey": hex64('c') } }), 571 log_error_delete 572 ); 573 574 assert_secondary_model_paths!( 575 nostr_event_head_scripted_region_paths, 576 INostrEventHeadCreate, 577 json!({ 578 "key": "state-a", 579 "kind": 30023, 580 "pubkey": hex64('d'), 581 "d_tag": "listing-a", 582 "last_event_id": hex64('e'), 583 "last_created_at": 1, 584 "content_hash": "hash-a" 585 }), 586 nostr_event_head_create, 587 INostrEventHeadFindMany, 588 json!({ "filter": { "id": "id-1" } }), 589 nostr_event_head_find_many, 590 INostrEventHeadFindOne, 591 json!({ "on": { "id": "id-1" } }), 592 nostr_event_head_find_one, 593 INostrEventHeadUpdate, 594 json!({ "on": { "id": "id-1" }, "fields": { "content_hash": "hash-z" } }), 595 json!({ "on": { "key": "state-a" }, "fields": { "content_hash": "hash-y" } }), 596 nostr_event_head_update, 597 INostrEventHeadDelete, 598 json!({ "on": { "key": "state-a" } }), 599 nostr_event_head_delete 600 ); 601 602 assert_rel_model_paths!( 603 gcs_location_scripted_region_paths, 604 IGcsLocationCreate, 605 json!({ 606 "d_tag": "gcs-a", 607 "lat": 59.33, 608 "lng": 18.06, 609 "geohash": "u6sce4f", 610 "point": "POINT(18.06 59.33)", 611 "polygon": "POLYGON((18.06 59.33,18.07 59.33,18.07 59.34,18.06 59.34,18.06 59.33))" 612 }), 613 gcs_location_create, 614 IGcsLocationFindMany, 615 json!({ "filter": { "id": "id-1" } }), 616 IGcsLocationFindMany::Rel { 617 rel: GcsLocationFindManyRel::OnFarm(GcsLocationFarmArgs { 618 id: String::from("farm-1") 619 }) 620 }, 621 gcs_location_find_many, 622 IGcsLocationFindOne, 623 json!({ "on": { "id": "id-1" } }), 624 IGcsLocationFindOne::Rel(IGcsLocationFindOneRelArgs { 625 rel: GcsLocationFindManyRel::OffTradeProduct(GcsLocationTradeProductArgs { 626 id: String::from("tp-1") 627 }) 628 }), 629 gcs_location_find_one, 630 IGcsLocationUpdate, 631 json!({ "on": { "id": "id-1" }, "fields": { "label": "z" } }), 632 json!({ "on": { "d_tag": "gcs-a" }, "fields": { "label": "y" } }), 633 gcs_location_update, 634 IGcsLocationDelete, 635 json!({ "on": { "d_tag": "gcs-a" } }), 636 IGcsLocationDelete::Rel(IGcsLocationFindOneRelArgs { 637 rel: GcsLocationFindManyRel::OnPlot(GcsLocationPlotArgs { 638 id: String::from("plot-1") 639 }) 640 }), 641 gcs_location_delete 642 ); 643 644 assert_rel_model_paths!( 645 media_image_scripted_region_paths, 646 IMediaImageCreate, 647 json!({ 648 "file_path": "/img/a.jpg", 649 "mime_type": "image/jpeg", 650 "res_base": "https://cdn.example.com", 651 "res_path": "img/a.jpg" 652 }), 653 media_image_create, 654 IMediaImageFindMany, 655 json!({ "filter": { "id": "id-1" } }), 656 IMediaImageFindMany::Rel { 657 rel: MediaImageFindManyRel::OnTradeProduct(MediaImageTradeProductArgs { 658 id: String::from("tp-1") 659 }) 660 }, 661 media_image_find_many, 662 IMediaImageFindOne, 663 json!({ "on": { "id": "id-1" } }), 664 IMediaImageFindOne::Rel(IMediaImageFindOneRelArgs { 665 rel: MediaImageFindManyRel::OffTradeProduct(MediaImageTradeProductArgs { 666 id: String::from("tp-1") 667 }) 668 }), 669 media_image_find_one, 670 IMediaImageUpdate, 671 json!({ "on": { "id": "id-1" }, "fields": { "label": "z" } }), 672 json!({ "on": { "file_path": "/img/a.jpg" }, "fields": { "label": "y" } }), 673 media_image_update, 674 IMediaImageDelete, 675 json!({ "on": { "file_path": "/img/a.jpg" } }), 676 IMediaImageDelete::Rel(IMediaImageFindOneRelArgs { 677 rel: MediaImageFindManyRel::OnTradeProduct(MediaImageTradeProductArgs { 678 id: String::from("tp-1") 679 }) 680 }), 681 media_image_delete 682 ); 683 684 assert_rel_model_paths!( 685 nostr_profile_scripted_region_paths, 686 INostrProfileCreate, 687 json!({ "public_key": hex64('d'), "profile_type": "farm", "name": "profile a" }), 688 nostr_profile_create, 689 INostrProfileFindMany, 690 json!({ "filter": { "id": "id-1" } }), 691 INostrProfileFindMany::Rel { 692 rel: NostrProfileFindManyRel::OnRelay(NostrProfileRelayArgs { 693 id: String::from("relay-1") 694 }) 695 }, 696 nostr_profile_find_many, 697 INostrProfileFindOne, 698 json!({ "on": { "id": "id-1" } }), 699 INostrProfileFindOne::Rel(INostrProfileFindOneRelArgs { 700 rel: NostrProfileFindManyRel::OffRelay(NostrProfileRelayArgs { 701 id: String::from("relay-1") 702 }) 703 }), 704 nostr_profile_find_one, 705 INostrProfileUpdate, 706 json!({ "on": { "id": "id-1" }, "fields": { "name": "z" } }), 707 json!({ "on": { "public_key": hex64('d') }, "fields": { "name": "y" } }), 708 nostr_profile_update, 709 INostrProfileDelete, 710 json!({ "on": { "public_key": hex64('d') } }), 711 INostrProfileDelete::Rel(INostrProfileFindOneRelArgs { 712 rel: NostrProfileFindManyRel::OnRelay(NostrProfileRelayArgs { 713 id: String::from("relay-1") 714 }) 715 }), 716 nostr_profile_delete 717 ); 718 719 assert_rel_model_paths!( 720 nostr_relay_scripted_region_paths, 721 INostrRelayCreate, 722 json!({ "url": "wss://relay.example.com" }), 723 nostr_relay_create, 724 INostrRelayFindMany, 725 json!({ "filter": { "id": "id-1" } }), 726 INostrRelayFindMany::Rel { 727 rel: NostrRelayFindManyRel::OnProfile(NostrRelayProfileArgs { 728 public_key: hex64('d') 729 }) 730 }, 731 nostr_relay_find_many, 732 INostrRelayFindOne, 733 json!({ "on": { "id": "id-1" } }), 734 INostrRelayFindOne::Rel(INostrRelayFindOneRelArgs { 735 rel: NostrRelayFindManyRel::OffProfile(NostrRelayProfileArgs { 736 public_key: hex64('d') 737 }) 738 }), 739 nostr_relay_find_one, 740 INostrRelayUpdate, 741 json!({ "on": { "id": "id-1" }, "fields": { "name": "z" } }), 742 json!({ "on": { "url": "wss://relay.example.com" }, "fields": { "name": "y" } }), 743 nostr_relay_update, 744 INostrRelayDelete, 745 json!({ "on": { "url": "wss://relay.example.com" } }), 746 INostrRelayDelete::Rel(INostrRelayFindOneRelArgs { 747 rel: NostrRelayFindManyRel::OnProfile(NostrRelayProfileArgs { 748 public_key: hex64('d') 749 }) 750 }), 751 nostr_relay_delete 752 ); 753 754 assert_trade_product_paths!( 755 trade_product_scripted_region_paths, 756 ITradeProductCreate, 757 json!({ 758 "key": "product-a", 759 "category": "coffee", 760 "title": "coffee a", 761 "summary": "summary", 762 "process": "washed", 763 "lot": "lot-a", 764 "profile": "floral", 765 "year": 2024, 766 "qty_amt": 100, 767 "qty_amt_exact": "100", 768 "qty_unit": "kg", 769 "price_amt": 7.5, 770 "price_amt_exact": "7.5", 771 "price_currency": "USD", 772 "price_qty_amt": 1, 773 "price_qty_amt_exact": "1", 774 "price_qty_unit": "kg" 775 }), 776 trade_product_create, 777 ITradeProductFindMany, 778 json!({ "filter": { "id": "id-1" } }), 779 trade_product_find_many, 780 ITradeProductFindOne, 781 json!({ "on": { "id": "id-1" } }), 782 trade_product_find_one, 783 ITradeProductUpdate, 784 json!({ "on": { "id": "id-1" }, "fields": { "title": "z" } }), 785 trade_product_update 786 );