1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//! # supplier_kit
//!
//! **A modular toolkit for managing and grouping dynamic data suppliers.**
//!
//! `supplier_kit` helps you build robust and extensible architectures that rely
//! on multiple external or internal data providers — known as *suppliers*. It is ideal
//! for use cases such as federated API calls, service orchestration, or data aggregation
//! (e.g., e-commerce platforms).
//!
//! ---
//!
//! ## ✨ Features
//!
//! - `Supplier` trait: defines a common interface for all data providers
//! - `SupplierRegistry`: a container for registering and accessing suppliers by name
//! - `SupplierGroup`: abstraction to query multiple suppliers in a batch
//! - `SupplierGroupResult`: returns per-supplier successes and failures
//! - `register_suppliers!` macro: for easy supplier registration
//! - Utility helpers like `add_supplier_from_registry` and `add_suppliers_from_registry` as an option
//!
//! ---
//!
//! ## 🔧 Use Cases
//!
//! - Aggregating product listings from multiple platforms
//! - Wrapping multiple internal microservices behind unified access
//! - Resilient systems that gracefully handle partial failure
//!
//! ---
//!
//! ## 🚀 Quick Start
//!
//! ### Example: Registering and Querying Multiple Suppliers
//!
//! This example demonstrates how to use `SupplierRegistry` and `BasicSupplierGroup`
//! to register multiple suppliers, group them, and execute a `Search` operation.
//!
//! It includes:
//! - Using the `register_suppliers!` macro
//! - Handling partial failures using `add_suppliers_from_registry`
//! - Group querying with `SupplierGroup` trait
//!
//! ```rust
//! use supplier_kit::models::{SupplierRequest, SupplierResponse, SupplierOperation};
//! use supplier_kit::supplier::{Supplier, SupplierRegistry};
//! use supplier_kit::supplier_group::{SupplierGroup, BasicSupplierGroup, SupplierGroupResult};
//! use supplier_kit::errors::SupplierError;
//! use supplier_kit::register_suppliers;
//! use serde_json::json;
//! use supplier_kit::utils::add_suppliers_from_registry;
//!
//! struct MockSupplier {
//! name: String,
//! should_fail: bool,
//! }
//!
//! impl MockSupplier {
//! fn new(name: &str, should_fail: bool) -> Self {
//! Self {
//! name: name.to_string(),
//! should_fail,
//! }
//! }
//! }
//!
//! impl Supplier for MockSupplier {
//! fn name(&self) -> &str {
//! &self.name
//! }
//!
//! fn query(&self, request: SupplierRequest) -> Result<SupplierResponse, SupplierError> {
//! if self.should_fail {
//! Err(SupplierError::Internal(format!("{} failed", self.name)))
//! } else {
//! Ok(SupplierResponse {
//! data: json!({
//! "supplier": self.name,
//! "params": request.params
//! }),
//! })
//! }
//! }
//! }
//!
//! fn main() -> Result<(), SupplierError> {
//! let mut registry = SupplierRegistry::new();
//! register_suppliers!(
//! registry,
//! "s1" => MockSupplier::new("s1", false),
//! "s2" => MockSupplier::new("s2", true),
//! "s3" => MockSupplier::new("s3", false),
//! );
//!
//! let mut group = BasicSupplierGroup::new("example_group");
//!
//! let failures = add_suppliers_from_registry(&mut group, ®istry, &["s1", "s2", "s4"]);
//!
//! if !failures.is_empty() {
//! for (name, err) in failures {
//! println!("Failed to add '{}': {}", name, err);
//! }
//! }
//!
//! let request = SupplierRequest {
//! operation: SupplierOperation::Search,
//! params: json!({ "keyword": "laptop" }),
//! };
//!
//! let result: SupplierGroupResult = group.query(request);
//!
//! println!("Successes:");
//! for (name, response) in result.successes {
//! println!("- [{}] Response: {}", name, response.data);
//! }
//!
//! println!("Failures:");
//! for (name, error) in result.failures {
//! println!("- [{}] Error: {}", name, error);
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! ---
//!
//! ## 📄 License
//!
//! Licensed under the [Apache-2.0 license](http://www.apache.org/licenses/LICENSE-2.0.txt)
//!
//! ---
//!
//! ## 👨 Author
//!
//! Jerry Maheswara <jerrymaheswara@gmail.com>
//!
//! ---
//!
//! ## ❤️ Built with Love in Rust
//!
//! This project is built with ❤️ using **Rust** — a systems programming language that is safe, fast, and concurrent.
//! Rust is the perfect choice for building reliable and efficient applications.
//!
//! ---
//!
//! ## 🤝 Contributing
//!
//! Pull requests, issues, and feedback are welcome!
//! If you find this crate useful, give it a ⭐ and share it with others in the Rustacean community.
//!
//! ---
/// Module for handling errors throughout the supplier kit.
///
/// It defines custom error types used within the crate, such as timeout,
/// unauthorized access, and internal errors.
/// Module containing common data models used by the supplier kit.
///
/// It defines structures such as `SupplierRequest`, `SupplierResponse`, and `SupplierOperation`,
/// which are used for communication between the system and suppliers.
/// Module for defining suppliers and their interactions.
///
/// This includes the `Supplier` trait that must be implemented by any provider (supplier),
/// as well as the `SupplierRegistry` for registering and retrieving suppliers.
/// Module for grouping suppliers together into logical collections.
///
/// This module defines the `SupplierGroup` trait and provides a default implementation
/// via `BasicSupplierGroup` to allow querying multiple suppliers at once.
/// Utility module for helper functions and internal logic.
///
/// This module contains utilities that are shared across other modules,
/// such as serialization or validation functions that aren't specific to one part of the crate.
/// Macros used throughout the supplier kit to improve ergonomics and reduce boilerplate code.
///
/// For example, macros for registering multiple suppliers in a concise manner.