@@ -20,7 +20,11 @@ pub(crate) struct Api {
20
20
}
21
21
22
22
impl Api {
23
- pub ( crate ) fn new ( paths : openapi:: Paths , with_deprecated : bool ) -> anyhow:: Result < Self > {
23
+ pub ( crate ) fn new (
24
+ paths : openapi:: Paths ,
25
+ with_deprecated : bool ,
26
+ component_schemas : & IndexMap < String , openapi:: SchemaObject > ,
27
+ ) -> anyhow:: Result < Self > {
24
28
let mut resources = BTreeMap :: new ( ) ;
25
29
26
30
for ( path, pi) in paths {
@@ -38,7 +42,9 @@ impl Api {
38
42
continue ;
39
43
}
40
44
41
- if let Some ( ( res_path, op) ) = Operation :: from_openapi ( & path, method, op) {
45
+ if let Some ( ( res_path, op) ) =
46
+ Operation :: from_openapi ( & path, method, op, component_schemas)
47
+ {
42
48
let resource = get_or_insert_resource ( & mut resources, res_path) ;
43
49
if op. method == "post" {
44
50
resource. has_post_operation = true ;
@@ -178,6 +184,10 @@ struct Operation {
178
184
/// Name of the request body type, if any.
179
185
#[ serde( skip_serializing_if = "Option::is_none" ) ]
180
186
request_body_schema_name : Option < String > ,
187
+ /// Some request bodies are required, but all the fields are optional (i.e. the CLI can omit
188
+ /// this from the argument list).
189
+ /// Only useful when `request_body_schema_name` is `Some`.
190
+ request_body_all_optional : bool ,
181
191
/// Name of the response body type, if any.
182
192
#[ serde( skip_serializing_if = "Option::is_none" ) ]
183
193
response_body_schema_name : Option < String > ,
@@ -189,6 +199,7 @@ impl Operation {
189
199
path : & str ,
190
200
method : & str ,
191
201
op : openapi:: Operation ,
202
+ component_schemas : & IndexMap < String , aide:: openapi:: SchemaObject > ,
192
203
) -> Option < ( Vec < String > , Self ) > {
193
204
let Some ( op_id) = op. operation_id else {
194
205
// ignore operations without an operationId
@@ -298,6 +309,51 @@ impl Operation {
298
309
}
299
310
}
300
311
312
+ let request_body_all_optional = op
313
+ . request_body
314
+ . as_ref ( )
315
+ . map ( |r| {
316
+ match r {
317
+ ReferenceOr :: Reference { .. } => {
318
+ unimplemented ! ( "reference" )
319
+ }
320
+ ReferenceOr :: Item ( body) => {
321
+ if let Some ( mt) = body. content . get ( "application/json" ) {
322
+ match mt. schema . as_ref ( ) . map ( |so| & so. json_schema ) {
323
+ Some ( Schema :: Object ( schemars:: schema:: SchemaObject {
324
+ object : Some ( ov) ,
325
+ ..
326
+ } ) ) => {
327
+ return ov. required . is_empty ( ) ;
328
+ }
329
+ Some ( Schema :: Object ( schemars:: schema:: SchemaObject {
330
+ reference : Some ( s) ,
331
+ ..
332
+ } ) ) => {
333
+ match component_schemas
334
+ . get (
335
+ & get_schema_name ( Some ( s) ) . expect ( "schema should exist" ) ,
336
+ )
337
+ . map ( |so| & so. json_schema )
338
+ {
339
+ Some ( Schema :: Object ( schemars:: schema:: SchemaObject {
340
+ object : Some ( ov) ,
341
+ ..
342
+ } ) ) => {
343
+ return ov. required . is_empty ( ) ;
344
+ }
345
+ _ => unimplemented ! ( "double ref not supported" ) ,
346
+ }
347
+ }
348
+ _ => { }
349
+ }
350
+ }
351
+ }
352
+ }
353
+ false
354
+ } )
355
+ . unwrap_or_default ( ) ;
356
+
301
357
let request_body_schema_name = op. request_body . and_then ( |b| match b {
302
358
ReferenceOr :: Item ( mut req_body) => {
303
359
assert ! ( req_body. required) ;
@@ -317,7 +373,7 @@ impl Operation {
317
373
if !obj. is_ref ( ) {
318
374
tracing:: error!( ?obj, "unexpected non-$ref json body schema" ) ;
319
375
}
320
- get_schema_name ( obj. reference )
376
+ get_schema_name ( obj. reference . as_deref ( ) )
321
377
}
322
378
}
323
379
}
@@ -370,6 +426,7 @@ impl Operation {
370
426
header_params,
371
427
query_params,
372
428
request_body_schema_name,
429
+ request_body_all_optional,
373
430
response_body_schema_name,
374
431
} ;
375
432
Some ( ( res_path, op) )
@@ -413,7 +470,7 @@ fn response_body_schema_name(resp: ReferenceOr<openapi::Response>) -> Option<Str
413
470
if !obj. is_ref ( ) {
414
471
tracing:: error!( ?obj, "unexpected non-$ref json body schema" ) ;
415
472
}
416
- get_schema_name ( obj. reference )
473
+ get_schema_name ( obj. reference . as_deref ( ) )
417
474
}
418
475
}
419
476
}
0 commit comments