Skip to content

Commit 918d484

Browse files
committed
- Fixed ferdikoomen#868 where (newly) required properties from base models would not get specified
1 parent 73acbca commit 918d484

10 files changed

+142
-28
lines changed

src/openApi/v2/parser/getEnumFromDescription.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import type { Enum } from '../../../client/interfaces/Enum';
22

3+
/**
4+
* @deprecated
5+
*/
36
export function getEnumFromDescription(description: string): Enum[] {
47
// Check if we can find this special format string:
58
// None=0,Something=1,AnotherThing=2

src/openApi/v2/parser/getModel.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,13 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
133133
model.base = 'any';
134134

135135
if (definition.properties) {
136-
const properties = getModelProperties(openApi, definition, getModel);
137-
properties.forEach(property => {
138-
model.imports.push(...property.imports);
139-
model.enums.push(...property.enums);
140-
model.properties.push(property);
141-
if (property.export === 'enum') {
142-
model.enums.push(property);
136+
const modelProperties = getModelProperties(openApi, definition, getModel);
137+
modelProperties.forEach(modelProperty => {
138+
model.imports.push(...modelProperty.imports);
139+
model.enums.push(...modelProperty.enums);
140+
model.properties.push(modelProperty);
141+
if (modelProperty.export === 'enum') {
142+
model.enums.push(modelProperty);
143143
}
144144
});
145145
}

src/openApi/v2/parser/getModelComposition.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import type { Model } from '../../../client/interfaces/Model';
12
import type { ModelComposition } from '../../../client/interfaces/ModelComposition';
23
import type { OpenApi } from '../interfaces/OpenApi';
34
import type { OpenApiSchema } from '../interfaces/OpenApiSchema';
45
import type { getModel } from './getModel';
56
import { getModelProperties } from './getModelProperties';
7+
import { getRequiredPropertiesFromComposition } from './getRequiredPropertiesFromComposition';
68

79
// Fix for circular dependency
810
export type GetModelFn = typeof getModel;
@@ -15,8 +17,10 @@ export function getModelComposition(openApi: OpenApi, definition: OpenApiSchema,
1517
properties: [],
1618
};
1719

18-
const models = definitions.map(definition => getModel(openApi, definition));
19-
models
20+
const properties: Model[] = [];
21+
22+
definitions
23+
.map(definition => getModel(openApi, definition))
2024
.filter(model => {
2125
const hasProperties = model.properties.length;
2226
const hasEnums = model.enums.length;
@@ -30,12 +34,25 @@ export function getModelComposition(openApi: OpenApi, definition: OpenApiSchema,
3034
composition.properties.push(model);
3135
});
3236

37+
if (definition.required) {
38+
const requiredProperties = getRequiredPropertiesFromComposition(openApi, definition.required, definitions, getModel);
39+
requiredProperties.forEach(requiredProperty => {
40+
composition.imports.push(...requiredProperty.imports);
41+
composition.enums.push(...requiredProperty.enums);
42+
});
43+
properties.push(...requiredProperties);
44+
}
45+
3346
if (definition.properties) {
34-
const properties = getModelProperties(openApi, definition, getModel);
35-
properties.forEach(property => {
36-
composition.imports.push(...property.imports);
37-
composition.enums.push(...property.enums);
47+
const modelProperties = getModelProperties(openApi, definition, getModel);
48+
modelProperties.forEach(modelProperty => {
49+
composition.imports.push(...modelProperty.imports);
50+
composition.enums.push(...modelProperty.enums);
3851
});
52+
properties.push(...modelProperties);
53+
}
54+
55+
if (properties) {
3956
composition.properties.push({
4057
name: 'properties',
4158
export: 'interface',
@@ -54,5 +71,6 @@ export function getModelComposition(openApi: OpenApi, definition: OpenApiSchema,
5471
properties,
5572
});
5673
}
74+
5775
return composition;
5876
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { Model } from '../../../client/interfaces/Model';
2+
import type { OpenApi } from '../interfaces/OpenApi';
3+
import type { OpenApiSchema } from '../interfaces/OpenApiSchema';
4+
import type { getModel } from './getModel';
5+
import { getRef } from './getRef';
6+
7+
// Fix for circular dependency
8+
export type GetModelFn = typeof getModel;
9+
10+
export function getRequiredPropertiesFromComposition(openApi: OpenApi, required: string[], definitions: OpenApiSchema[], getModel: GetModelFn): Model[] {
11+
return definitions
12+
.reduce((properties, definition) => {
13+
if (definition.$ref) {
14+
const schema = getRef<OpenApiSchema>(openApi, definition);
15+
return [...properties, ...getModel(openApi, schema).properties];
16+
}
17+
return [...properties, ...getModel(openApi, definition).properties];
18+
}, [] as Model[])
19+
.filter(property => {
20+
return !property.isRequired && required.includes(property.name);
21+
})
22+
.map(property => {
23+
return {
24+
...property,
25+
isRequired: true,
26+
};
27+
});
28+
}

src/openApi/v3/parser/getEnumFromDescription.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import type { Enum } from '../../../client/interfaces/Enum';
22

3+
/**
4+
* @deprecated
5+
*/
36
export function getEnumFromDescription(description: string): Enum[] {
47
// Check if we can find this special format string:
58
// None=0,Something=1,AnotherThing=2

src/openApi/v3/parser/getModel.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,13 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
160160
model.default = getModelDefault(definition, model);
161161

162162
if (definition.properties) {
163-
const properties = getModelProperties(openApi, definition, getModel);
164-
properties.forEach(property => {
165-
model.imports.push(...property.imports);
166-
model.enums.push(...property.enums);
167-
model.properties.push(property);
168-
if (property.export === 'enum') {
169-
model.enums.push(property);
163+
const modelProperties = getModelProperties(openApi, definition, getModel);
164+
modelProperties.forEach(modelProperty => {
165+
model.imports.push(...modelProperty.imports);
166+
model.enums.push(...modelProperty.enums);
167+
model.properties.push(modelProperty);
168+
if (modelProperty.export === 'enum') {
169+
model.enums.push(modelProperty);
170170
}
171171
});
172172
}

src/openApi/v3/parser/getModelComposition.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import type { Model } from '../../../client/interfaces/Model';
12
import type { ModelComposition } from '../../../client/interfaces/ModelComposition';
23
import type { OpenApi } from '../interfaces/OpenApi';
34
import type { OpenApiSchema } from '../interfaces/OpenApiSchema';
45
import type { getModel } from './getModel';
56
import { getModelProperties } from './getModelProperties';
7+
import { getRequiredPropertiesFromComposition } from './getRequiredPropertiesFromComposition';
68

79
// Fix for circular dependency
810
export type GetModelFn = typeof getModel;
@@ -15,8 +17,10 @@ export function getModelComposition(openApi: OpenApi, definition: OpenApiSchema,
1517
properties: [],
1618
};
1719

18-
const models = definitions.map(definition => getModel(openApi, definition));
19-
models
20+
const properties: Model[] = [];
21+
22+
definitions
23+
.map(definition => getModel(openApi, definition))
2024
.filter(model => {
2125
const hasProperties = model.properties.length;
2226
const hasEnums = model.enums.length;
@@ -30,12 +34,25 @@ export function getModelComposition(openApi: OpenApi, definition: OpenApiSchema,
3034
composition.properties.push(model);
3135
});
3236

37+
if (definition.required) {
38+
const requiredProperties = getRequiredPropertiesFromComposition(openApi, definition.required, definitions, getModel);
39+
requiredProperties.forEach(requiredProperty => {
40+
composition.imports.push(...requiredProperty.imports);
41+
composition.enums.push(...requiredProperty.enums);
42+
});
43+
properties.push(...requiredProperties);
44+
}
45+
3346
if (definition.properties) {
34-
const properties = getModelProperties(openApi, definition, getModel);
35-
properties.forEach(property => {
36-
composition.imports.push(...property.imports);
37-
composition.enums.push(...property.enums);
47+
const modelProperties = getModelProperties(openApi, definition, getModel);
48+
modelProperties.forEach(modelProperty => {
49+
composition.imports.push(...modelProperty.imports);
50+
composition.enums.push(...modelProperty.enums);
3851
});
52+
properties.push(...modelProperties);
53+
}
54+
55+
if (properties.length) {
3956
composition.properties.push({
4057
name: 'properties',
4158
export: 'interface',
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { Model } from '../../../client/interfaces/Model';
2+
import type { OpenApi } from '../interfaces/OpenApi';
3+
import type { OpenApiSchema } from '../interfaces/OpenApiSchema';
4+
import type { getModel } from './getModel';
5+
import { getRef } from './getRef';
6+
7+
// Fix for circular dependency
8+
export type GetModelFn = typeof getModel;
9+
10+
export function getRequiredPropertiesFromComposition(openApi: OpenApi, required: string[], definitions: OpenApiSchema[], getModel: GetModelFn): Model[] {
11+
return definitions
12+
.reduce((properties, definition) => {
13+
if (definition.$ref) {
14+
const schema = getRef<OpenApiSchema>(openApi, definition);
15+
return [...properties, ...getModel(openApi, schema).properties];
16+
}
17+
return [...properties, ...getModel(openApi, definition).properties];
18+
}, [] as Model[])
19+
.filter(property => {
20+
return !property.isRequired && required.includes(property.name);
21+
})
22+
.map(property => {
23+
return {
24+
...property,
25+
isRequired: true,
26+
};
27+
});
28+
}

src/openApi/v3/parser/getType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { stripNamespace } from './stripNamespace';
55
function encode(value: string): string {
66
return value.replace(/^[^a-zA-Z_$]+/g, '').replace(/[^\w$]+/g, '_');
77
}
8+
89
/**
910
* Parse any string value into a type object.
1011
* @param values String or String[] value like "integer", "Link[Model]" or ["string", "null"]

test/__snapshots__/index.spec.js.snap

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ import type { ModelWithString } from './ModelWithString';
811811
export type ModelThatExtends = (ModelWithString & {
812812
propExtendsA?: string;
813813
propExtendsB?: ModelWithString;
814-
});
814+
} & any);
815815
"
816816
`;
817817

@@ -829,7 +829,7 @@ import type { ModelWithString } from './ModelWithString';
829829
export type ModelThatExtendsExtends = (ModelWithString & ModelThatExtends & {
830830
propExtendsC?: string;
831831
propExtendsD?: ModelWithString;
832-
});
832+
} & any);
833833
"
834834
`;
835835

@@ -1478,6 +1478,9 @@ export const $ModelThatExtends = {
14781478
type: 'ModelWithString',
14791479
},
14801480
},
1481+
}, {
1482+
properties: {
1483+
},
14811484
}],
14821485
};"
14831486
`;
@@ -1501,6 +1504,9 @@ export const $ModelThatExtendsExtends = {
15011504
type: 'ModelWithString',
15021505
},
15031506
},
1507+
}, {
1508+
properties: {
1509+
},
15041510
}],
15051511
};"
15061512
`;
@@ -3201,6 +3207,8 @@ import type { CompositionBaseModel } from './CompositionBaseModel';
32013207
* This is a model that extends the base model
32023208
*/
32033209
export type CompositionExtendedModel = (CompositionBaseModel & {
3210+
firstName: string;
3211+
lastname: string;
32043212
age: number;
32053213
});
32063214
"
@@ -4055,6 +4063,14 @@ export const $CompositionExtendedModel = {
40554063
type: 'CompositionBaseModel',
40564064
}, {
40574065
properties: {
4066+
firstName: {
4067+
type: 'string',
4068+
isRequired: true,
4069+
},
4070+
lastname: {
4071+
type: 'string',
4072+
isRequired: true,
4073+
},
40584074
age: {
40594075
type: 'number',
40604076
isRequired: true,

0 commit comments

Comments
 (0)