Handle operations whose response is a `null`
This commit is contained in:
parent
a3fbbc06ba
commit
75b224c047
|
@ -101,12 +101,6 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dtoa"
|
|
||||||
version = "0.4.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dyn-clone"
|
name = "dyn-clone"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -410,12 +404,6 @@ version = "0.2.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
|
checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linked-hash-map"
|
|
||||||
version = "0.5.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
|
@ -525,14 +513,13 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openapiv3"
|
name = "openapiv3"
|
||||||
version = "1.0.0-beta.2"
|
version = "1.0.0-beta.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "791f5f66415ca5d11fb29e8dcf0b923adff5b2c9bd1cf54621777494c8f8f688"
|
checksum = "d45518fa48878a21efa793483d3c5a3dd5f8f98026fc3dade65104d8b78bb535"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -944,18 +931,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_yaml"
|
|
||||||
version = "0.8.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af"
|
|
||||||
dependencies = [
|
|
||||||
"dtoa",
|
|
||||||
"indexmap",
|
|
||||||
"serde",
|
|
||||||
"yaml-rust",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
@ -1366,11 +1341,6 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[patch.unused]]
|
||||||
name = "yaml-rust"
|
name = "typify"
|
||||||
version = "0.4.5"
|
version = "0.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
|
||||||
dependencies = [
|
|
||||||
"linked-hash-map",
|
|
||||||
]
|
|
||||||
|
|
|
@ -15,5 +15,5 @@ default-members = [
|
||||||
"progenitor-macro",
|
"progenitor-macro",
|
||||||
]
|
]
|
||||||
|
|
||||||
#[patch."https://github.com/oxidecomputer/typify"]
|
[patch."https://github.com/oxidecomputer/typify"]
|
||||||
#typify = { path = "../typify/typify" }
|
typify = { path = "../typify/typify" }
|
||||||
|
|
|
@ -10,7 +10,7 @@ description = "An OpenAPI client generator - core implementation"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
getopts = "0.2"
|
getopts = "0.2"
|
||||||
indexmap = "1.7"
|
indexmap = "1.7"
|
||||||
openapiv3 = "1.0.0-beta.2"
|
openapiv3 = "1.0.0-beta.5"
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
regex = "1.5"
|
regex = "1.5"
|
||||||
|
|
|
@ -105,6 +105,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
read_only,
|
read_only,
|
||||||
write_only,
|
write_only,
|
||||||
example,
|
example,
|
||||||
|
extensions,
|
||||||
} = self.schema_data.clone();
|
} = self.schema_data.clone();
|
||||||
|
|
||||||
let metadata = schemars::schema::Metadata {
|
let metadata = schemars::schema::Metadata {
|
||||||
|
@ -143,6 +144,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
pattern: pattern.clone(),
|
pattern: pattern.clone(),
|
||||||
}))
|
}))
|
||||||
.reduce(),
|
.reduce(),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
openapiv3::SchemaKind::Type(openapiv3::Type::Number(
|
openapiv3::SchemaKind::Type(openapiv3::Type::Number(
|
||||||
|
@ -186,6 +188,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.reduce(),
|
.reduce(),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,6 +236,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.reduce(),
|
.reduce(),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,6 +265,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
property_names: None,
|
property_names: None,
|
||||||
}))
|
}))
|
||||||
.reduce(),
|
.reduce(),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -290,6 +295,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
contains: None,
|
contains: None,
|
||||||
}))
|
}))
|
||||||
.reduce(),
|
.reduce(),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -300,6 +306,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
schemars::schema::InstanceType::Boolean,
|
schemars::schema::InstanceType::Boolean,
|
||||||
nullable,
|
nullable,
|
||||||
),
|
),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,6 +319,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,6 +332,7 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,12 +345,27 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openapiv3::SchemaKind::Not { not } => {
|
||||||
|
schemars::schema::SchemaObject {
|
||||||
|
subschemas: Some(Box::new(
|
||||||
|
schemars::schema::SubschemaValidation {
|
||||||
|
not: Some(Box::new(not.convert())),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the permissive schema that allows anything to match.
|
// This is the permissive schema that allows anything to match.
|
||||||
openapiv3::SchemaKind::Any(AnySchema {
|
openapiv3::SchemaKind::Any(AnySchema {
|
||||||
|
typ: None,
|
||||||
pattern: None,
|
pattern: None,
|
||||||
multiple_of: None,
|
multiple_of: None,
|
||||||
exclusive_minimum: None,
|
exclusive_minimum: None,
|
||||||
|
@ -358,12 +382,73 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
max_items: None,
|
max_items: None,
|
||||||
unique_items: None,
|
unique_items: None,
|
||||||
format: None,
|
format: None,
|
||||||
}) if properties.is_empty() && required.is_empty() => {
|
enumeration,
|
||||||
schemars::schema::Schema::Bool(true).into_object()
|
min_length: None,
|
||||||
|
max_length: None,
|
||||||
|
one_of,
|
||||||
|
all_of,
|
||||||
|
any_of,
|
||||||
|
not: None,
|
||||||
|
}) if properties.is_empty()
|
||||||
|
&& required.is_empty()
|
||||||
|
&& enumeration.is_empty()
|
||||||
|
&& one_of.is_empty()
|
||||||
|
&& all_of.is_empty()
|
||||||
|
&& any_of.is_empty() =>
|
||||||
|
{
|
||||||
|
let mut schema =
|
||||||
|
schemars::schema::Schema::Bool(true).into_object();
|
||||||
|
schema.extensions = extensions.into_iter().collect();
|
||||||
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
// Malformed object.
|
// A simple null value.
|
||||||
openapiv3::SchemaKind::Any(AnySchema {
|
openapiv3::SchemaKind::Any(AnySchema {
|
||||||
|
typ: None,
|
||||||
|
pattern: None,
|
||||||
|
multiple_of: None,
|
||||||
|
exclusive_minimum: None,
|
||||||
|
exclusive_maximum: None,
|
||||||
|
minimum: None,
|
||||||
|
maximum: None,
|
||||||
|
properties,
|
||||||
|
required,
|
||||||
|
additional_properties: None,
|
||||||
|
min_properties: None,
|
||||||
|
max_properties: None,
|
||||||
|
items: None,
|
||||||
|
min_items: None,
|
||||||
|
max_items: None,
|
||||||
|
unique_items: None,
|
||||||
|
format: None,
|
||||||
|
enumeration,
|
||||||
|
min_length: None,
|
||||||
|
max_length: None,
|
||||||
|
one_of,
|
||||||
|
all_of,
|
||||||
|
any_of,
|
||||||
|
not: None,
|
||||||
|
}) if properties.is_empty()
|
||||||
|
&& required.is_empty()
|
||||||
|
&& enumeration.len() == 1
|
||||||
|
&& enumeration[0] == serde_json::Value::Null
|
||||||
|
&& one_of.is_empty()
|
||||||
|
&& all_of.is_empty()
|
||||||
|
&& any_of.is_empty() =>
|
||||||
|
{
|
||||||
|
schemars::schema::SchemaObject {
|
||||||
|
metadata,
|
||||||
|
instance_type: Some(
|
||||||
|
schemars::schema::InstanceType::Null.into(),
|
||||||
|
),
|
||||||
|
extensions: extensions.into_iter().collect(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Malformed object with 'type' not set.
|
||||||
|
openapiv3::SchemaKind::Any(AnySchema {
|
||||||
|
typ: None,
|
||||||
pattern: None,
|
pattern: None,
|
||||||
multiple_of: None,
|
multiple_of: None,
|
||||||
exclusive_minimum: None,
|
exclusive_minimum: None,
|
||||||
|
@ -380,7 +465,18 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
max_items: None,
|
max_items: None,
|
||||||
unique_items: None,
|
unique_items: None,
|
||||||
format: None,
|
format: None,
|
||||||
}) => {
|
enumeration,
|
||||||
|
min_length: None,
|
||||||
|
max_length: None,
|
||||||
|
one_of,
|
||||||
|
all_of,
|
||||||
|
any_of,
|
||||||
|
not: None,
|
||||||
|
}) if enumeration.is_empty()
|
||||||
|
&& one_of.is_empty()
|
||||||
|
&& all_of.is_empty()
|
||||||
|
&& any_of.is_empty() =>
|
||||||
|
{
|
||||||
let object = openapiv3::Schema {
|
let object = openapiv3::Schema {
|
||||||
schema_data: self.schema_data.clone(),
|
schema_data: self.schema_data.clone(),
|
||||||
schema_kind: openapiv3::SchemaKind::Type(
|
schema_kind: openapiv3::SchemaKind::Type(
|
||||||
|
@ -397,8 +493,9 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
object.convert().into()
|
object.convert().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Malformed array.
|
// Malformed array with 'type' not set.
|
||||||
openapiv3::SchemaKind::Any(AnySchema {
|
openapiv3::SchemaKind::Any(AnySchema {
|
||||||
|
typ: None,
|
||||||
pattern: None,
|
pattern: None,
|
||||||
multiple_of: None,
|
multiple_of: None,
|
||||||
exclusive_minimum: None,
|
exclusive_minimum: None,
|
||||||
|
@ -415,7 +512,20 @@ impl Convert<schemars::schema::Schema> for openapiv3::Schema {
|
||||||
max_items,
|
max_items,
|
||||||
unique_items,
|
unique_items,
|
||||||
format: None,
|
format: None,
|
||||||
}) if properties.is_empty() && required.is_empty() => {
|
enumeration,
|
||||||
|
min_length: None,
|
||||||
|
max_length: None,
|
||||||
|
one_of,
|
||||||
|
all_of,
|
||||||
|
any_of,
|
||||||
|
not: None,
|
||||||
|
}) if properties.is_empty()
|
||||||
|
&& required.is_empty()
|
||||||
|
&& enumeration.is_empty()
|
||||||
|
&& one_of.is_empty()
|
||||||
|
&& all_of.is_empty()
|
||||||
|
&& any_of.is_empty() =>
|
||||||
|
{
|
||||||
let array = openapiv3::Schema {
|
let array = openapiv3::Schema {
|
||||||
schema_data: self.schema_data.clone(),
|
schema_data: self.schema_data.clone(),
|
||||||
schema_kind: openapiv3::SchemaKind::Type(
|
schema_kind: openapiv3::SchemaKind::Type(
|
||||||
|
@ -493,14 +603,22 @@ impl Convert<Value> for Option<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Convert<Value> for f64 {
|
impl Convert<Value> for Option<f64> {
|
||||||
fn convert(&self) -> Value {
|
fn convert(&self) -> Value {
|
||||||
Value::Number(serde_json::Number::from_f64(*self).unwrap())
|
match self {
|
||||||
|
Some(value) => {
|
||||||
|
Value::Number(serde_json::Number::from_f64(*value).unwrap())
|
||||||
|
}
|
||||||
|
None => Value::Null,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Convert<Value> for i64 {
|
impl Convert<Value> for Option<i64> {
|
||||||
fn convert(&self) -> Value {
|
fn convert(&self) -> Value {
|
||||||
Value::Number(serde_json::Number::from(*self))
|
match self {
|
||||||
|
Some(value) => Value::Number(serde_json::Number::from(*value)),
|
||||||
|
None => Value::Null,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,14 +627,9 @@ fn instance_type(
|
||||||
nullable: bool,
|
nullable: bool,
|
||||||
) -> Option<schemars::schema::SingleOrVec<schemars::schema::InstanceType>> {
|
) -> Option<schemars::schema::SingleOrVec<schemars::schema::InstanceType>> {
|
||||||
if nullable {
|
if nullable {
|
||||||
Some(schemars::schema::SingleOrVec::Vec(vec![
|
Some(vec![instance_type, schemars::schema::InstanceType::Null].into())
|
||||||
instance_type,
|
|
||||||
schemars::schema::InstanceType::Null,
|
|
||||||
]))
|
|
||||||
} else {
|
} else {
|
||||||
Some(schemars::schema::SingleOrVec::Single(Box::new(
|
Some(instance_type.into())
|
||||||
instance_type,
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,3 +704,25 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::to_schema::Convert;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_null() {
|
||||||
|
let schema_value = json!({ "enum": [null] });
|
||||||
|
let oa_schema =
|
||||||
|
serde_json::from_value::<openapiv3::Schema>(schema_value).unwrap();
|
||||||
|
|
||||||
|
let schema = oa_schema.convert();
|
||||||
|
assert_eq!(
|
||||||
|
schema.into_object().instance_type,
|
||||||
|
Some(schemars::schema::SingleOrVec::Single(Box::new(
|
||||||
|
schemars::schema::InstanceType::Null
|
||||||
|
)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ impl Client {
|
||||||
let request = self.client.post(url).build()?;
|
let request = self.client.post(url).build()?;
|
||||||
let result = self.client.execute(request).await;
|
let result = self.client.execute(request).await;
|
||||||
let res = result?.error_for_status()?;
|
let res = result?.error_for_status()?;
|
||||||
Ok(())
|
Ok(res.json().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "control_resume: POST /v1/control/resume"]
|
#[doc = "control_resume: POST /v1/control/resume"]
|
||||||
|
|
|
@ -10,7 +10,16 @@
|
||||||
"operationId": "control_hold",
|
"operationId": "control_hold",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "successful operation"
|
"description": "successful operation",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"enum": [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue