Skip to content

Commit e2f488e

Browse files
committed
Add infra to generate codesamples
1 parent 3e8a7f8 commit e2f488e

File tree

10 files changed

+637
-290
lines changed

10 files changed

+637
-290
lines changed

src/api/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::collections::{BTreeSet, btree_map};
22

3-
mod resources;
4-
mod struct_enum;
5-
mod types;
3+
pub(crate) mod resources;
4+
pub(crate) mod struct_enum;
5+
pub(crate) mod types;
66

77
use aide::openapi;
88
use serde::{Deserialize, Serialize};

src/api/resources.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl Resource {
105105

106106
for operation in &self.operations {
107107
for param in &operation.query_params {
108-
if let FieldType::SchemaRef { name } = &param.r#type {
108+
if let FieldType::SchemaRef { name, inner: None } = &param.r#type {
109109
res.insert(name);
110110
}
111111
}
@@ -125,7 +125,7 @@ impl Resource {
125125
#[derive(Deserialize, Serialize)]
126126
pub(crate) struct Operation {
127127
/// The operation ID from the spec.
128-
id: String,
128+
pub(crate) id: String,
129129
/// The name to use for the operation in code.
130130
pub(crate) name: String,
131131
/// Description of the operation to use for documentation.
@@ -151,7 +151,7 @@ pub(crate) struct Operation {
151151
query_params: Vec<QueryParam>,
152152
/// Name of the request body type, if any.
153153
#[serde(skip_serializing_if = "Option::is_none")]
154-
request_body_schema_name: Option<String>,
154+
pub(crate) request_body_schema_name: Option<String>,
155155
/// Some request bodies are required, but all the fields are optional (i.e. the CLI can omit
156156
/// this from the argument list).
157157
/// Only useful when `request_body_schema_name` is `Some`.

src/api/struct_enum.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ impl TypeData {
4848
if variant.properties.len() == 1 {
4949
variants.push(SimpleVariant {
5050
name: discriminator,
51-
content: EnumVariantType::Ref { schema_ref: None },
51+
content: EnumVariantType::Ref {
52+
schema_ref: None,
53+
inner: None,
54+
},
5255
});
5356
} else {
5457
let (variant_content_field, content) = get_content(variant)?;
@@ -91,6 +94,7 @@ fn get_content(variant: &ObjectValidation) -> anyhow::Result<(String, EnumVarian
9194
p_name.to_owned(),
9295
EnumVariantType::Ref {
9396
schema_ref: Some(get_schema_name(Some(schema_ref.as_str())).unwrap()),
97+
inner: None,
9498
},
9599
));
96100
}

src/api/types.rs

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ pub(crate) fn from_referenced_components(
7979
types
8080
}
8181

82-
#[derive(Deserialize, Serialize)]
82+
#[derive(Deserialize, Serialize, Debug, Clone)]
8383
pub(crate) struct Type {
8484
name: String,
8585
#[serde(skip_serializing_if = "Option::is_none")]
8686
description: Option<String>,
8787
deprecated: bool,
8888
#[serde(flatten)]
89-
data: TypeData,
89+
pub data: TypeData,
9090
}
9191

9292
impl Type {
@@ -159,7 +159,7 @@ fn fields_referenced_schemas(fields: &[Field]) -> BTreeSet<&str> {
159159
.collect()
160160
}
161161

162-
#[derive(Deserialize, Serialize)]
162+
#[derive(Deserialize, Serialize, Debug, Clone)]
163163
#[serde(tag = "kind", rename_all = "snake_case")]
164164
pub(crate) enum TypeData {
165165
Struct {
@@ -270,7 +270,7 @@ impl TypeData {
270270
}
271271
}
272272

273-
#[derive(Deserialize, Serialize)]
273+
#[derive(Deserialize, Serialize, Debug, Clone)]
274274
#[serde(tag = "repr", rename_all = "snake_case")]
275275
pub(crate) enum StructEnumRepr {
276276
// add more variants here to support other enum representations
@@ -295,25 +295,27 @@ impl StructEnumRepr {
295295
EnumVariantType::Struct { fields } => {
296296
fields.iter().find_map(|f| f.r#type.referenced_schema())
297297
}
298-
EnumVariantType::Ref { schema_ref } => schema_ref.as_deref(),
298+
EnumVariantType::Ref { schema_ref, .. } => schema_ref.as_deref(),
299299
})
300300
.collect(),
301301
}
302302
}
303303
}
304304

305-
#[derive(Deserialize, Serialize, Clone)]
305+
#[derive(Deserialize, Serialize, Debug, Clone)]
306306
pub(crate) struct Field {
307307
name: String,
308308
#[serde(serialize_with = "serialize_field_type")]
309-
r#type: FieldType,
309+
pub r#type: FieldType,
310310
#[serde(skip_serializing_if = "Option::is_none")]
311311
default: Option<serde_json::Value>,
312312
#[serde(skip_serializing_if = "Option::is_none")]
313313
description: Option<String>,
314314
required: bool,
315315
nullable: bool,
316316
deprecated: bool,
317+
#[serde(skip_serializing_if = "Option::is_none")]
318+
example: Option<serde_json::Value>,
317319
}
318320

319321
impl Field {
@@ -322,14 +324,14 @@ impl Field {
322324
Schema::Bool(_) => bail!("unsupported bool schema"),
323325
Schema::Object(o) => o,
324326
};
327+
let example = obj.extensions.get("example").cloned();
325328
let metadata = obj.metadata.clone().unwrap_or_default();
326329

327330
let nullable = obj
328331
.extensions
329332
.get("nullable")
330333
.and_then(|v| v.as_bool())
331334
.unwrap_or(false);
332-
333335
Ok(Self {
334336
name,
335337
r#type: FieldType::from_schema_object(obj)?,
@@ -338,11 +340,12 @@ impl Field {
338340
required,
339341
nullable,
340342
deprecated: metadata.deprecated,
343+
example,
341344
})
342345
}
343346
}
344347

345-
#[derive(Deserialize, Serialize)]
348+
#[derive(Deserialize, Serialize, Debug, Clone)]
346349
#[serde(tag = "type", rename_all = "camelCase")]
347350
pub(crate) enum EnumVariantType {
348351
Struct {
@@ -351,10 +354,12 @@ pub(crate) enum EnumVariantType {
351354
Ref {
352355
#[serde(skip_serializing_if = "Option::is_none")]
353356
schema_ref: Option<String>,
357+
#[serde(skip_serializing_if = "Option::is_none")]
358+
inner: Option<Type>,
354359
},
355360
}
356361

357-
#[derive(Deserialize, Serialize)]
362+
#[derive(Deserialize, Serialize, Debug, Clone)]
358363
pub(crate) struct SimpleVariant {
359364
/// Discriminator value that identifies this variant.
360365
pub name: String,
@@ -396,6 +401,8 @@ pub(crate) enum FieldType {
396401
/// The name of another schema that defines this type.
397402
SchemaRef {
398403
name: String,
404+
#[serde(skip_serializing_if = "Option::is_none")]
405+
inner: Option<Type>,
399406
},
400407

401408
/// A string constant, used as an enum discriminator value.
@@ -515,7 +522,7 @@ impl FieldType {
515522
bail!("unsupported multi-typed parameter: `{types:?}`")
516523
}
517524
None => match get_schema_name(obj.reference.as_deref()) {
518-
Some(name) => Self::SchemaRef { name },
525+
Some(name) => Self::SchemaRef { name, inner: None },
519526
None => bail!("unsupported type-less parameter"),
520527
},
521528
};
@@ -545,7 +552,7 @@ impl FieldType {
545552
Self::List { inner } | Self::Set { inner } => {
546553
format!("List<{}>", inner.to_csharp_typename()).into()
547554
}
548-
Self::SchemaRef { name } => filter_schema_ref(name, "Object"),
555+
Self::SchemaRef { name, .. } => filter_schema_ref(name, "Object"),
549556
Self::StringConst { .. } => "string".into(),
550557
}
551558
}
@@ -565,7 +572,7 @@ impl FieldType {
565572
Self::List { inner } | Self::Set { inner } => {
566573
format!("[]{}", inner.to_go_typename()).into()
567574
}
568-
Self::SchemaRef { name } => filter_schema_ref(name, "map[string]any"),
575+
Self::SchemaRef { name, .. } => filter_schema_ref(name, "map[string]any"),
569576
Self::StringConst { .. } => "string".into(),
570577
}
571578
}
@@ -586,7 +593,7 @@ impl FieldType {
586593
Self::JsonObject => "Map<String,Any>".into(),
587594
Self::List { inner } => format!("List<{}>", inner.to_kotlin_typename()).into(),
588595
Self::Set { inner } => format!("Set<{}>", inner.to_kotlin_typename()).into(),
589-
Self::SchemaRef { name } => filter_schema_ref(name, "Map<String,Any>"),
596+
Self::SchemaRef { name, .. } => filter_schema_ref(name, "Map<String,Any>"),
590597
Self::StringConst { .. } => "String".into(),
591598
}
592599
}
@@ -606,7 +613,7 @@ impl FieldType {
606613
Self::Map { value_ty } => {
607614
format!("{{ [key: string]: {} }}", value_ty.to_js_typename()).into()
608615
}
609-
Self::SchemaRef { name } => filter_schema_ref(name, "any"),
616+
Self::SchemaRef { name, .. } => filter_schema_ref(name, "any"),
610617
Self::StringConst { .. } => "string".into(),
611618
}
612619
}
@@ -633,14 +640,14 @@ impl FieldType {
633640
value_ty.to_rust_typename(),
634641
)
635642
.into(),
636-
Self::SchemaRef { name } => filter_schema_ref(name, "serde_json::Value"),
643+
Self::SchemaRef { name,.. } => filter_schema_ref(name, "serde_json::Value"),
637644
Self::StringConst { .. } => "String".into()
638645
}
639646
}
640647

641648
pub(crate) fn referenced_schema(&self) -> Option<&str> {
642649
match self {
643-
Self::SchemaRef { name } => {
650+
Self::SchemaRef { name, .. } => {
644651
// TODO(10055): the `BackgroundTaskFinishedEvent2` struct has a field with type of `Data`
645652
// this corresponds to a `#[serde(untagged)]` enum `svix_server::v1::endpoints::background_tasks::Data`
646653
// we should change this server side, but for now I am changing it here
@@ -659,7 +666,7 @@ impl FieldType {
659666
Self::Int16 | Self::UInt16 | Self::Int32 | Self::Int64 | Self::UInt64 => "int".into(),
660667
Self::String => "str".into(),
661668
Self::DateTime => "datetime".into(),
662-
Self::SchemaRef { name } => filter_schema_ref(name, "t.Dict[str, t.Any]"),
669+
Self::SchemaRef { name, .. } => filter_schema_ref(name, "t.Dict[str, t.Any]"),
663670
Self::Uri => "str".into(),
664671
Self::JsonObject => "t.Dict[str, t.Any]".into(),
665672
Self::Set { inner } | Self::List { inner } => {
@@ -690,15 +697,15 @@ impl FieldType {
690697
FieldType::Map { value_ty } => {
691698
format!("Map<String,{}>", value_ty.to_java_typename()).into()
692699
}
693-
FieldType::SchemaRef { name } => filter_schema_ref(name, "Object"),
700+
FieldType::SchemaRef { name, .. } => filter_schema_ref(name, "Object"),
694701
// backwards compat
695702
FieldType::StringConst { .. } => "TypeEnum".into(),
696703
}
697704
}
698705

699706
fn to_ruby_typename(&self) -> Cow<'_, str> {
700707
match self {
701-
FieldType::SchemaRef { name } => name.clone().into(),
708+
FieldType::SchemaRef { name, .. } => name.clone().into(),
702709
FieldType::StringConst { .. } => {
703710
unreachable!("FieldType::const should never be exposed to template code")
704711
}
@@ -745,7 +752,7 @@ impl FieldType {
745752
| FieldType::List { .. }
746753
| FieldType::Set { .. }
747754
| FieldType::Map { .. } => "array".into(),
748-
FieldType::SchemaRef { name } => name.clone().into(),
755+
FieldType::SchemaRef { name, .. } => name.clone().into(),
749756
}
750757
}
751758
}
@@ -827,6 +834,10 @@ impl minijinja::value::Object for FieldType {
827834
ensure_no_args(args, "is_string")?;
828835
Ok(matches!(**self, Self::String).into())
829836
}
837+
"is_uri" => {
838+
ensure_no_args(args, "is_uri")?;
839+
Ok(matches!(**self, Self::Uri).into())
840+
}
830841
"is_bool" => {
831842
ensure_no_args(args, "is_bool")?;
832843
Ok(matches!(**self, Self::Bool).into())
@@ -870,6 +881,17 @@ impl minijinja::value::Object for FieldType {
870881
};
871882
Ok(ty.into())
872883
}
884+
"inner_schema_ref_ty" => {
885+
ensure_no_args(args, "inner_schema_ref_ty")?;
886+
let ty = match &**self {
887+
FieldType::SchemaRef { inner, .. } => {
888+
let i = inner.as_ref().unwrap().clone();
889+
Some(minijinja::Value::from_serialize(i))
890+
}
891+
_ => None,
892+
};
893+
Ok(ty.into())
894+
}
873895
// Returns the value type of a map
874896
"value_type" => {
875897
ensure_no_args(args, "value_type")?;

0 commit comments

Comments
 (0)