Skip to content

Commit b259de4

Browse files
authored
fix: Incorrect nested object. (#185)
1 parent 0e4b1df commit b259de4

24 files changed

Lines changed: 130 additions & 152 deletions

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
#### 🐞 Fixes
6+
7+
- Fixed an incorrect double nested object for flattened fields.
8+
39
## 0.19.3
410

511
#### 🚀 Updates

crates/schematic/examples/show_error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(unused)]
2+
13
use schematic::*;
24

35
#[derive(Config)]

crates/schematic/src/schema/renderers/json_schema.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ impl SchemaRenderer<JsonSchema> for JsonSchemaRenderer {
438438
) -> RenderResult<JsonSchema> {
439439
let mut properties = BTreeMap::new();
440440
let mut required = BTreeSet::from_iter(structure.required.clone().unwrap_or_default());
441-
let mut additional_properties = JsonSchema::Bool(false);
441+
let mut additional_properties = Some(Box::new(JsonSchema::Bool(false)));
442442
let exclude_aliases = self.options.exclude_aliases;
443443

444444
for (name, field) in &structure.fields {
@@ -447,7 +447,19 @@ impl SchemaRenderer<JsonSchema> for JsonSchemaRenderer {
447447
}
448448

449449
if field.flatten {
450-
additional_properties = self.render_schema_without_reference(&field.schema)?;
450+
if let Some(schema) = field.schema.get_nonnull_schema() {
451+
let flattened = self.render_schema_without_reference(schema)?;
452+
453+
if matches!(schema.ty, SchemaType::Object(_))
454+
&& let JsonSchema::Object(inner) = flattened.clone()
455+
&& let Some(object) = inner.object
456+
{
457+
additional_properties = object.additional_properties;
458+
} else {
459+
additional_properties = Some(Box::new(flattened));
460+
}
461+
}
462+
451463
continue;
452464
}
453465

@@ -471,7 +483,7 @@ impl SchemaRenderer<JsonSchema> for JsonSchemaRenderer {
471483
metadata: Some(Box::new(self.create_metadata_from_schema(schema))),
472484
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Object))),
473485
object: Some(Box::new(ObjectValidation {
474-
additional_properties: Some(Box::new(additional_properties)),
486+
additional_properties,
475487
required,
476488
properties,
477489
..Default::default()

crates/schematic/src/schema/renderers/typescript.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,9 @@ impl TypeScriptRenderer {
158158
fn export_object_type(&mut self, name: &str, schema: &Schema, value: String) -> RenderResult {
159159
let mut tags = vec![];
160160

161-
let output = if !value.contains(" & ")
162-
&& matches!(self.options.object_format, ObjectFormat::Interface)
161+
let output = if matches!(self.options.object_format, ObjectFormat::Interface)
162+
&& value.starts_with('{')
163+
&& value.ends_with('}')
163164
{
164165
format!("export interface {name} {value}")
165166
} else {
@@ -189,18 +190,16 @@ impl TypeScriptRenderer {
189190
// Extract flattened fields first as we'll need to use intersections
190191
// to support them correctly in TypeScript
191192
for (field_name, field) in &structure.fields {
192-
if field.flatten {
193+
if field.flatten
194+
&& let Some(schema) = field.schema.get_nonnull_schema()
195+
{
193196
let name = format!(
194197
"{name}{}",
195198
field_name.from_case(Case::Snake).to_case(Case::Pascal)
196199
);
197-
let value = self.render_schema(&field.schema)?;
200+
let value = self.render_schema(schema)?;
198201

199-
outputs.push(self.export_object_type(
200-
&name,
201-
&field.schema,
202-
format!("{{ [key: string]: {value} }}"),
203-
)?);
202+
outputs.push(self.export_object_type(&name, &field.schema, value)?);
204203
extends.push(name);
205204
}
206205
}

crates/schematic/tests/snapshots/generator_test__json_schema__defaults.snap

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -213,20 +213,14 @@ expression: "fs::read_to_string(file).unwrap()"
213213
}
214214
},
215215
"additionalProperties": {
216-
"type": "object",
217-
"additionalProperties": {
218-
"type": [
219-
"boolean",
220-
"object",
221-
"array",
222-
"number",
223-
"string",
224-
"integer"
225-
]
226-
},
227-
"propertyNames": {
228-
"type": "string"
229-
}
216+
"type": [
217+
"boolean",
218+
"object",
219+
"array",
220+
"number",
221+
"string",
222+
"integer"
223+
]
230224
},
231225
"definitions": {
232226
"AnotherConfig": {

crates/schematic/tests/snapshots/generator_test__json_schema__not_required.snap

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -184,20 +184,14 @@ expression: "fs::read_to_string(file).unwrap()"
184184
}
185185
},
186186
"additionalProperties": {
187-
"type": "object",
188-
"additionalProperties": {
189-
"type": [
190-
"boolean",
191-
"object",
192-
"array",
193-
"number",
194-
"string",
195-
"integer"
196-
]
197-
},
198-
"propertyNames": {
199-
"type": "string"
200-
}
187+
"type": [
188+
"boolean",
189+
"object",
190+
"array",
191+
"number",
192+
"string",
193+
"integer"
194+
]
201195
},
202196
"definitions": {
203197
"AnotherConfig": {

crates/schematic/tests/snapshots/generator_test__json_schema__partials.snap

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -333,26 +333,13 @@ expression: "fs::read_to_string(file).unwrap()"
333333
}
334334
},
335335
"additionalProperties": {
336-
"anyOf": [
337-
{
338-
"type": "object",
339-
"additionalProperties": {
340-
"type": [
341-
"boolean",
342-
"object",
343-
"array",
344-
"number",
345-
"string",
346-
"integer"
347-
]
348-
},
349-
"propertyNames": {
350-
"type": "string"
351-
}
352-
},
353-
{
354-
"type": "null"
355-
}
336+
"type": [
337+
"boolean",
338+
"object",
339+
"array",
340+
"number",
341+
"string",
342+
"integer"
356343
]
357344
},
358345
"definitions": {
@@ -628,20 +615,14 @@ expression: "fs::read_to_string(file).unwrap()"
628615
}
629616
},
630617
"additionalProperties": {
631-
"type": "object",
632-
"additionalProperties": {
633-
"type": [
634-
"boolean",
635-
"object",
636-
"array",
637-
"number",
638-
"string",
639-
"integer"
640-
]
641-
},
642-
"propertyNames": {
643-
"type": "string"
644-
}
618+
"type": [
619+
"boolean",
620+
"object",
621+
"array",
622+
"number",
623+
"string",
624+
"integer"
625+
]
645626
}
646627
},
647628
"PartialAnotherConfig": {

crates/schematic/tests/snapshots/generator_test__json_schema__with_markdown_descs.snap

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -215,20 +215,14 @@ expression: "fs::read_to_string(file).unwrap()"
215215
}
216216
},
217217
"additionalProperties": {
218-
"type": "object",
219-
"additionalProperties": {
220-
"type": [
221-
"boolean",
222-
"object",
223-
"array",
224-
"number",
225-
"string",
226-
"integer"
227-
]
228-
},
229-
"propertyNames": {
230-
"type": "string"
231-
}
218+
"type": [
219+
"boolean",
220+
"object",
221+
"array",
222+
"number",
223+
"string",
224+
"integer"
225+
]
232226
},
233227
"definitions": {
234228
"AnotherConfig": {

crates/schematic/tests/snapshots/generator_test__json_schema__with_titles.snap

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -239,20 +239,14 @@ expression: "fs::read_to_string(file).unwrap()"
239239
}
240240
},
241241
"additionalProperties": {
242-
"type": "object",
243-
"additionalProperties": {
244-
"type": [
245-
"boolean",
246-
"object",
247-
"array",
248-
"number",
249-
"string",
250-
"integer"
251-
]
252-
},
253-
"propertyNames": {
254-
"type": "string"
255-
}
242+
"type": [
243+
"boolean",
244+
"object",
245+
"array",
246+
"number",
247+
"string",
248+
"integer"
249+
]
256250
},
257251
"definitions": {
258252
"AnotherConfig": {

crates/schematic/tests/snapshots/generator_test__typescript__const_enums.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export interface AnotherConfig {
2727
opt: string | null;
2828
}
2929

30-
export interface GenConfigFlattened { [key: string]: Record<string, unknown> }
30+
export type GenConfigFlattened = Record<string, unknown>;
3131

3232
/** @deprecated */
3333
export interface GenConfigBase {

0 commit comments

Comments
 (0)