@@ -28,7 +28,11 @@ pub(crate) struct Api {
28
28
}
29
29
30
30
impl Api {
31
- pub ( crate ) fn new ( paths : openapi:: Paths , with_deprecated : bool ) -> anyhow:: Result < Self > {
31
+ pub ( crate ) fn new (
32
+ paths : openapi:: Paths ,
33
+ with_deprecated : bool ,
34
+ component_schemas : IndexMap < String , aide:: openapi:: SchemaObject > ,
35
+ ) -> anyhow:: Result < Self > {
32
36
let mut resources = BTreeMap :: new ( ) ;
33
37
34
38
for ( path, pi) in paths {
@@ -46,7 +50,9 @@ impl Api {
46
50
continue ;
47
51
}
48
52
49
- if let Some ( ( res_path, op) ) = Operation :: from_openapi ( & path, method, op) {
53
+ if let Some ( ( res_path, op) ) =
54
+ Operation :: from_openapi ( & path, method, op, & component_schemas)
55
+ {
50
56
let resource = get_or_insert_resource ( & mut resources, res_path) ;
51
57
if op. method == "post" {
52
58
resource. has_post_operation = true ;
@@ -223,6 +229,10 @@ struct Operation {
223
229
/// Name of the request body type, if any.
224
230
#[ serde( skip_serializing_if = "Option::is_none" ) ]
225
231
request_body_schema_name : Option < String > ,
232
+ /// Some request bodies are required, but all the fields are optional (i.e. the CLI can omit
233
+ /// this from the argument list).
234
+ /// Only useful when `request_body_schema_name` is `Some`.
235
+ request_body_all_optional : bool ,
226
236
/// Name of the response body type, if any.
227
237
#[ serde( skip_serializing_if = "Option::is_none" ) ]
228
238
response_body_schema_name : Option < String > ,
@@ -234,6 +244,7 @@ impl Operation {
234
244
path : & str ,
235
245
method : & str ,
236
246
op : openapi:: Operation ,
247
+ component_schemas : & IndexMap < String , aide:: openapi:: SchemaObject > ,
237
248
) -> Option < ( Vec < String > , Self ) > {
238
249
let Some ( op_id) = op. operation_id else {
239
250
// ignore operations without an operationId
@@ -343,7 +354,7 @@ impl Operation {
343
354
}
344
355
}
345
356
346
- let request_body_schema_name = op. request_body . and_then ( |b| match b {
357
+ let request_body_schema_name = op. request_body . clone ( ) . and_then ( |b| match b {
347
358
ReferenceOr :: Item ( mut req_body) => {
348
359
assert ! ( req_body. required) ;
349
360
assert ! ( req_body. extensions. is_empty( ) ) ;
@@ -372,6 +383,53 @@ impl Operation {
372
383
}
373
384
} ) ;
374
385
386
+ let request_body_all_optional = op
387
+ . request_body
388
+ . map ( |r| {
389
+ match r {
390
+ ReferenceOr :: Reference { .. } => {
391
+ todo ! ( "reference" )
392
+ }
393
+ ReferenceOr :: Item ( body) => {
394
+ if let Some ( mt) = body. content . get ( "application/json" ) {
395
+ match mt. schema . as_ref ( ) . map ( |so| & so. json_schema ) {
396
+ Some ( Schema :: Object ( schemars:: schema:: SchemaObject {
397
+ object : Some ( ov) ,
398
+ ..
399
+ } ) ) => {
400
+ dbg ! ( ( & op_id, ov. required. is_empty( ) ) ) ;
401
+ return ov. required . is_empty ( ) ;
402
+ }
403
+ Some ( Schema :: Object ( schemars:: schema:: SchemaObject {
404
+ reference : Some ( s) ,
405
+ ..
406
+ } ) ) => {
407
+ match component_schemas
408
+ . get (
409
+ & get_schema_name ( Some ( s. clone ( ) ) )
410
+ . expect ( "schema should exist" ) ,
411
+ )
412
+ . map ( |so| & so. json_schema )
413
+ {
414
+ Some ( Schema :: Object ( schemars:: schema:: SchemaObject {
415
+ object : Some ( ov) ,
416
+ ..
417
+ } ) ) => {
418
+ dbg ! ( ( & op_id, ov. required. is_empty( ) ) ) ;
419
+ return ov. required . is_empty ( ) ;
420
+ }
421
+ _ => todo ! ( "just give up at the double ref" ) ,
422
+ }
423
+ }
424
+ _ => { }
425
+ }
426
+ }
427
+ }
428
+ }
429
+ false
430
+ } )
431
+ . unwrap_or_default ( ) ;
432
+
375
433
let response_body_schema_name = op. responses . and_then ( |r| {
376
434
assert_eq ! ( r. default , None ) ;
377
435
assert ! ( r. extensions. is_empty( ) ) ;
@@ -415,6 +473,7 @@ impl Operation {
415
473
header_params,
416
474
query_params,
417
475
request_body_schema_name,
476
+ request_body_all_optional,
418
477
response_body_schema_name,
419
478
} ;
420
479
Some ( ( res_path, op) )
0 commit comments