Skip to main content

reinhardt_urls/
proxy.rs

1//! # Reinhardt Association Proxy
2//!
3//! SQLAlchemy-style association proxies for transparent attribute access through relationships.
4//!
5//! ## Overview
6//!
7//! Association proxies allow you to access attributes on related objects as if they were
8//! attributes on the parent object. This is particularly useful for many-to-many relationships
9//! where you want to work with related objects' attributes directly.
10//!
11//! ## Example
12//!
13//! ```rust,no_run
14//! # use reinhardt_urls::proxy::AssociationProxy;
15//!
16//! # #[derive(Clone)]
17//! # struct User {
18//! #     id: i64,
19//! #     user_keywords: Vec<UserKeyword>,
20//! # }
21//! # #[derive(Clone)]
22//! # struct UserKeyword {
23//! #     user_id: i64,
24//! #     keyword_id: i64,
25//! #     keyword: Keyword,
26//! # }
27//! # #[derive(Clone)]
28//! # struct Keyword {
29//! #     id: i64,
30//! #     name: String,
31//! # }
32//!
33//! // Create proxy to access keyword names directly
34//! let keywords_proxy: AssociationProxy<UserKeyword, String> =
35//!     AssociationProxy::new("user_keywords", "keyword");
36//! // let keyword_names: Vec<String> = keywords_proxy.get_names(&user).await?;
37//! ```
38
39pub mod builder;
40pub mod collection;
41pub mod joins;
42pub mod lazy_url;
43pub mod loading;
44pub mod orm_integration;
45// Allow module_inception: Re-exporting proxy submodule from proxy.rs
46// is intentional for compatibility with existing imports (`reinhardt_urls::proxy::URLProxy`)
47#[allow(clippy::module_inception)]
48pub mod proxy;
49pub mod query;
50pub mod reflection;
51pub mod scalar;
52pub mod url_namespace;
53pub mod url_pattern;
54pub mod url_resolver;
55
56pub use builder::{ProxyBuilder, association_proxy};
57pub use collection::{CollectionAggregations, CollectionOperations, CollectionProxy};
58pub use joins::{
59	CircularReferenceError, JoinConfig, NestedProxy, RelationshipPath, extract_through_path,
60	filter_through_path, traverse_and_extract, traverse_relationships,
61};
62// Re-export LoadingStrategy from reinhardt-orm for consistency
63pub use lazy_url::LazyUrl;
64pub use loading::{
65	EagerLoadConfig, EagerLoadable, LazyLoadable, LazyLoaded, LoadStrategy, RelationshipCache,
66};
67pub use orm_integration::OrmReflectable;
68pub use reinhardt_db::orm::LoadingStrategy;
69
70// Note: impl_orm_reflectable macro is exported at crate root via #[macro_export]
71// and can be used directly as reinhardt_urls::proxy::impl_orm_reflectable!
72pub use proxy::{AssociationProxy, ProxyAccessor, ProxyTarget, ScalarValue};
73pub use query::{FilterCondition, FilterOp, QueryFilter};
74pub use reflection::{
75	AttributeExtractor, ProxyCollection, Reflectable, ReflectableFactory, downcast_relationship,
76	extract_collection_values,
77};
78pub use scalar::{ScalarComparison, ScalarProxy};
79pub use url_namespace::UrlNamespace;
80pub use url_pattern::UrlPattern;
81pub use url_resolver::UrlResolver;
82
83use thiserror::Error;
84
85/// Result type for association proxy operations
86pub type ProxyResult<T> = Result<T, ProxyError>;
87
88/// Errors that can occur in association proxy operations
89#[derive(Debug, Error)]
90pub enum ProxyError {
91	/// Target relationship not found
92	#[error("Target relationship '{0}' not found")]
93	RelationshipNotFound(String),
94
95	/// Attribute not found on target object
96	#[error("Attribute '{0}' not found on target")]
97	AttributeNotFound(String),
98
99	/// Type mismatch in proxy operation
100	#[error("Type mismatch: expected {expected}, got {actual}")]
101	TypeMismatch {
102		/// The expected type name.
103		expected: String,
104		/// The actual type name encountered.
105		actual: String,
106	},
107
108	/// Invalid proxy configuration
109	#[error("Invalid proxy configuration: {0}")]
110	InvalidConfiguration(String),
111
112	/// Database error during proxy operation
113	#[error("Database error: {0}")]
114	DatabaseError(String),
115
116	/// Serialization error
117	#[error("Serialization error: {0}")]
118	SerializationError(String),
119
120	/// Factory not configured for collection proxy
121	#[error(
122		"Factory not configured for collection proxy - required for creating objects from scalar values"
123	)]
124	FactoryNotConfigured,
125
126	/// Version tracking not enabled
127	#[error("Version tracking is not enabled for this proxy")]
128	VersionTrackingNotEnabled,
129
130	/// Version mismatch during update
131	#[error("Version mismatch: expected {expected}, got {actual}")]
132	VersionMismatch {
133		/// The expected version number.
134		expected: i64,
135		/// The actual version number encountered.
136		actual: i64,
137	},
138}