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