@@ -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( ) ) ;
@@ -362,7 +373,7 @@ impl Operation {
362
373
if !obj. is_ref ( ) {
363
374
tracing:: error!( ?obj, "unexpected non-$ref json body schema" ) ;
364
375
}
365
- get_schema_name ( obj. reference )
376
+ get_schema_name ( obj. reference . as_deref ( ) )
366
377
}
367
378
}
368
379
}
@@ -372,6 +383,50 @@ 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
+ return ov. required . is_empty ( ) ;
401
+ }
402
+ Some ( Schema :: Object ( schemars:: schema:: SchemaObject {
403
+ reference : Some ( s) ,
404
+ ..
405
+ } ) ) => {
406
+ match component_schemas
407
+ . get (
408
+ & get_schema_name ( Some ( s) ) . expect ( "schema should exist" ) ,
409
+ )
410
+ . map ( |so| & so. json_schema )
411
+ {
412
+ Some ( Schema :: Object ( schemars:: schema:: SchemaObject {
413
+ object : Some ( ov) ,
414
+ ..
415
+ } ) ) => {
416
+ return ov. required . is_empty ( ) ;
417
+ }
418
+ _ => unimplemented ! ( "double ref not supported" ) ,
419
+ }
420
+ }
421
+ _ => { }
422
+ }
423
+ }
424
+ }
425
+ }
426
+ false
427
+ } )
428
+ . unwrap_or_default ( ) ;
429
+
375
430
let response_body_schema_name = op. responses . and_then ( |r| {
376
431
assert_eq ! ( r. default , None ) ;
377
432
assert ! ( r. extensions. is_empty( ) ) ;
@@ -415,6 +470,7 @@ impl Operation {
415
470
header_params,
416
471
query_params,
417
472
request_body_schema_name,
473
+ request_body_all_optional,
418
474
response_body_schema_name,
419
475
} ;
420
476
Some ( ( res_path, op) )
@@ -458,7 +514,7 @@ fn response_body_schema_name(resp: ReferenceOr<openapi::Response>) -> Option<Str
458
514
if !obj. is_ref ( ) {
459
515
tracing:: error!( ?obj, "unexpected non-$ref json body schema" ) ;
460
516
}
461
- get_schema_name ( obj. reference )
517
+ get_schema_name ( obj. reference . as_deref ( ) )
462
518
}
463
519
}
464
520
}
0 commit comments