Skip to content

Commit fc55ad2

Browse files
committed
fix(parser): type additional properties with properties
1 parent 22eef6c commit fc55ad2

File tree

4 files changed

+101
-38
lines changed

4 files changed

+101
-38
lines changed

src/openApi/v3/parser/getModel.ts

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { extendEnum } from './extendEnum';
66
import { getEnum } from './getEnum';
77
import { findModelComposition, getModelComposition } from './getModelComposition';
88
import { getModelDefault } from './getModelDefault';
9-
import { getModelProperties } from './getModelProperties';
9+
import { getAdditionalPropertiesModel, getModelProperties } from './getModelProperties';
1010
import { getType } from './getType';
1111

1212
export const getModel = (
@@ -103,33 +103,6 @@ export const getModel = (
103103
return model;
104104
}
105105

106-
if (
107-
definition.type === 'object' &&
108-
(typeof definition.additionalProperties === 'object' || definition.additionalProperties === true)
109-
) {
110-
const ap = typeof definition.additionalProperties === 'object' ? definition.additionalProperties : {};
111-
if (ap.$ref) {
112-
const additionalProperties = getType(ap.$ref);
113-
model.export = 'dictionary';
114-
model.type = additionalProperties.type;
115-
model.base = additionalProperties.base;
116-
model.template = additionalProperties.template;
117-
model.imports.push(...additionalProperties.imports);
118-
model.default = getModelDefault(definition, model);
119-
return model;
120-
} else {
121-
const additionalProperties = getModel(openApi, ap);
122-
model.export = 'dictionary';
123-
model.type = additionalProperties.type;
124-
model.base = additionalProperties.base;
125-
model.template = additionalProperties.template;
126-
model.link = additionalProperties;
127-
model.imports.push(...additionalProperties.imports);
128-
model.default = getModelDefault(definition, model);
129-
return model;
130-
}
131-
}
132-
133106
const foundComposition = findModelComposition(definition);
134107
if (foundComposition) {
135108
const composition = getModelComposition({
@@ -158,18 +131,16 @@ export const getModel = (
158131
model.enums.push(modelProperty);
159132
}
160133
});
161-
return model;
162-
} else {
163-
const additionalProperties = getModel(openApi, {});
164-
model.export = 'dictionary';
165-
model.type = additionalProperties.type;
166-
model.base = additionalProperties.base;
167-
model.template = additionalProperties.template;
168-
model.link = additionalProperties;
169-
model.imports.push(...additionalProperties.imports);
170-
model.default = getModelDefault(definition, model);
134+
135+
if (definition.additionalProperties === true) {
136+
const modelProperty = getAdditionalPropertiesModel(openApi, definition, getModel, model);
137+
model.properties.push(modelProperty);
138+
}
139+
171140
return model;
172141
}
142+
143+
return getAdditionalPropertiesModel(openApi, definition, getModel, model);
173144
}
174145

175146
if (definition.const !== undefined) {

src/openApi/v3/parser/getModelProperties.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,50 @@ import type { OpenApi } from '../interfaces/OpenApi';
55
import type { OpenApiSchema } from '../interfaces/OpenApiSchema';
66
import { escapeName } from './escapeName';
77
import type { getModel } from './getModel';
8+
import { getModelDefault } from './getModelDefault';
89
import { getType } from './getType';
910

1011
// Fix for circular dependency
1112
export type GetModelFn = typeof getModel;
1213

14+
export const getAdditionalPropertiesModel = (
15+
openApi: OpenApi,
16+
definition: OpenApiSchema,
17+
getModel: GetModelFn,
18+
model: Model
19+
): Model => {
20+
const ap = typeof definition.additionalProperties === 'object' ? definition.additionalProperties : {};
21+
const apModel = getModel(openApi, ap);
22+
23+
if (definition.additionalProperties === true && definition.properties) {
24+
apModel.default = getModelDefault(definition, model);
25+
apModel.export = 'generic';
26+
apModel.isRequired = true;
27+
apModel.name = '[key: string]';
28+
return apModel;
29+
}
30+
31+
if (ap.$ref) {
32+
const apType = getType(ap.$ref);
33+
model.base = apType.base;
34+
model.default = getModelDefault(definition, model);
35+
model.export = 'dictionary';
36+
model.imports.push(...apType.imports);
37+
model.template = apType.template;
38+
model.type = apType.type;
39+
return model;
40+
}
41+
42+
model.base = apModel.base;
43+
model.default = getModelDefault(definition, model);
44+
model.export = 'dictionary';
45+
model.imports.push(...apModel.imports);
46+
model.link = apModel;
47+
model.template = apModel.template;
48+
model.type = apModel.type;
49+
return model;
50+
};
51+
1352
export const getModelProperties = (
1453
openApi: OpenApi,
1554
definition: OpenApiSchema,

test/__snapshots__/index.spec.ts.snap

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3740,6 +3740,7 @@ export type { ModelCircle } from './models/ModelCircle';
37403740
export type { ModelSquare } from './models/ModelSquare';
37413741
export type { ModelThatExtends } from './models/ModelThatExtends';
37423742
export type { ModelThatExtendsExtends } from './models/ModelThatExtendsExtends';
3743+
export type { ModelWithAdditionalPropertiesEqTrue } from './models/ModelWithAdditionalPropertiesEqTrue';
37433744
export type { ModelWithArray } from './models/ModelWithArray';
37443745
export type { ModelWithBoolean } from './models/ModelWithBoolean';
37453746
export type { ModelWithCircularReference } from './models/ModelWithCircularReference';
@@ -3819,6 +3820,7 @@ export { $ModelCircle } from './schemas/$ModelCircle';
38193820
export { $ModelSquare } from './schemas/$ModelSquare';
38203821
export { $ModelThatExtends } from './schemas/$ModelThatExtends';
38213822
export { $ModelThatExtendsExtends } from './schemas/$ModelThatExtendsExtends';
3823+
export { $ModelWithAdditionalPropertiesEqTrue } from './schemas/$ModelWithAdditionalPropertiesEqTrue';
38223824
export { $ModelWithArray } from './schemas/$ModelWithArray';
38233825
export { $ModelWithBoolean } from './schemas/$ModelWithBoolean';
38243826
export { $ModelWithCircularReference } from './schemas/$ModelWithCircularReference';
@@ -4650,6 +4652,25 @@ export type ModelThatExtendsExtends = (ModelWithString & ModelThatExtends & {
46504652
"
46514653
`;
46524654

4655+
exports[`v3 should generate: test/generated/v3/models/ModelWithAdditionalPropertiesEqTrue.ts 1`] = `
4656+
"/* generated using openapi-typescript-codegen -- do no edit */
4657+
/* istanbul ignore file */
4658+
/* tslint:disable */
4659+
/* eslint-disable */
4660+
/**
4661+
* This is a model with one property and additionalProperties: true
4662+
*/
4663+
export type ModelWithAdditionalPropertiesEqTrue = {
4664+
/**
4665+
* This is a simple string property
4666+
*/
4667+
prop?: string;
4668+
[key: string]: any;
4669+
};
4670+
4671+
"
4672+
`;
4673+
46534674
exports[`v3 should generate: test/generated/v3/models/ModelWithArray.ts 1`] = `
46544675
"/* generated using openapi-typescript-codegen -- do no edit */
46554676
/* istanbul ignore file */
@@ -6143,6 +6164,27 @@ export const $ModelThatExtendsExtends = {
61436164
"
61446165
`;
61456166

6167+
exports[`v3 should generate: test/generated/v3/schemas/$ModelWithAdditionalPropertiesEqTrue.ts 1`] = `
6168+
"/* generated using openapi-typescript-codegen -- do no edit */
6169+
/* istanbul ignore file */
6170+
/* tslint:disable */
6171+
/* eslint-disable */
6172+
export const $ModelWithAdditionalPropertiesEqTrue = {
6173+
description: \`This is a model with one property and additionalProperties: true\`,
6174+
properties: {
6175+
prop: {
6176+
type: 'string',
6177+
description: \`This is a simple string property\`,
6178+
},
6179+
[key: string]: {
6180+
type: 'any',
6181+
isRequired: true,
6182+
},
6183+
},
6184+
} as const;
6185+
"
6186+
`;
6187+
61466188
exports[`v3 should generate: test/generated/v3/schemas/$ModelWithArray.ts 1`] = `
61476189
"/* generated using openapi-typescript-codegen -- do no edit */
61486190
/* istanbul ignore file */

test/spec/v3.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2737,6 +2737,17 @@
27372737
}
27382738
}
27392739
},
2740+
"ModelWithAdditionalPropertiesEqTrue": {
2741+
"description": "This is a model with one property and additionalProperties: true",
2742+
"type": "object",
2743+
"properties": {
2744+
"prop": {
2745+
"description": "This is a simple string property",
2746+
"type": "string"
2747+
}
2748+
},
2749+
"additionalProperties": true
2750+
},
27402751
"NestedAnyOfArraysNullable": {
27412752
"properties": {
27422753
"nullableArray": {

0 commit comments

Comments
 (0)