v08_features/
v08_features.rs1use domainstack_schema::{OpenApiBuilder, Schema, ToSchema};
10use serde_json::json;
11
12#[allow(dead_code)]
16struct PaymentMethod {
17 method_type: String,
18}
19
20impl ToSchema for PaymentMethod {
21 fn schema_name() -> &'static str {
22 "PaymentMethod"
23 }
24
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40#[allow(dead_code)]
42struct AdminUser {
43 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }
221}
222
223#[allow(dead_code)]
226struct User {
227 email: String,
228 name: String,
229}
230
231impl ToSchema for User {
232 fn schema_name() -> &'static str {
233 "User"
234 }
235
236 fn schema() -> Schema {
237 Schema::object()
238 .property("email", Schema::string().format("email"))
239 .property("name", Schema::string().min_length(1))
240 .required(&["email", "name"])
241 }
242}
243
244fn main() {
245 let spec = OpenApiBuilder::new("v0.8 Features Demo", "1.0.0")
246 .description("Demonstrates OpenAPI v0.8 features: composition, metadata, and extensions")
247 .register::<PaymentMethod>()
248 .register::<AdminUser>()
249 .register::<User>()
250 .register::<UserSettings>()
251 .register::<UserAccount>()
252 .register::<DateRange>()
253 .register::<OrderForm>()
254 .build();
255
256 println!("{}", spec.to_json().expect("Failed to serialize"));
257
258 println!("\n=== v0.8 Features Demonstrated ===");
259 println!("[ok] anyOf: PaymentMethod (union of card | cash)");
260 println!("[ok] allOf: AdminUser (extends User)");
261 println!("[ok] default: UserSettings.theme = 'auto'");
262 println!("[ok] example: UserSettings.theme example = 'dark'");
263 println!("[ok] examples: UserSettings.language examples = ['en', 'es', 'fr']");
264 println!("[ok] readOnly: UserAccount.id, createdAt (response only)");
265 println!("[ok] writeOnly: UserAccount.password (request only)");
266 println!("[ok] deprecated: UserAccount.oldUsername");
267 println!("[ok] vendor extensions: DateRange, OrderForm (x-domainstack-validations)");
268 println!("\nAll v0.8 features working correctly!");
269}