Skip to content

Commit 4379538

Browse files
authored
Merge pull request ferdikoomen#1165 from kshramt/free-form-object
Support free-form objects
2 parents 168da7a + e003116 commit 4379538

File tree

3 files changed

+125
-13
lines changed

3 files changed

+125
-13
lines changed

src/openApi/v3/parser/getModel.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,13 @@ export const getModel = (
9595
}
9696
}
9797

98-
if (definition.type === 'object' && typeof definition.additionalProperties === 'object') {
99-
if (definition.additionalProperties.$ref) {
100-
const additionalProperties = getType(definition.additionalProperties.$ref);
98+
if (
99+
definition.type === 'object' &&
100+
(typeof definition.additionalProperties === 'object' || definition.additionalProperties === true)
101+
) {
102+
const ap = typeof definition.additionalProperties === 'object' ? definition.additionalProperties : {};
103+
if (ap.$ref) {
104+
const additionalProperties = getType(ap.$ref);
101105
model.export = 'dictionary';
102106
model.type = additionalProperties.type;
103107
model.base = additionalProperties.base;
@@ -106,7 +110,7 @@ export const getModel = (
106110
model.default = getModelDefault(definition, model);
107111
return model;
108112
} else {
109-
const additionalProperties = getModel(openApi, definition.additionalProperties);
113+
const additionalProperties = getModel(openApi, ap);
110114
model.export = 'dictionary';
111115
model.type = additionalProperties.type;
112116
model.base = additionalProperties.base;
@@ -146,12 +150,12 @@ export const getModel = (
146150
}
147151

148152
if (definition.type === 'object') {
149-
model.export = 'interface';
150-
model.type = 'any';
151-
model.base = 'any';
152-
model.default = getModelDefault(definition, model);
153-
154153
if (definition.properties) {
154+
model.export = 'interface';
155+
model.type = 'any';
156+
model.base = 'any';
157+
model.default = getModelDefault(definition, model);
158+
155159
const modelProperties = getModelProperties(openApi, definition, getModel, model);
156160
modelProperties.forEach(modelProperty => {
157161
model.imports.push(...modelProperty.imports);
@@ -161,8 +165,18 @@ export const getModel = (
161165
model.enums.push(modelProperty);
162166
}
163167
});
168+
return model;
169+
} else {
170+
const additionalProperties = getModel(openApi, {});
171+
model.export = 'dictionary';
172+
model.type = additionalProperties.type;
173+
model.base = additionalProperties.base;
174+
model.template = additionalProperties.template;
175+
model.link = additionalProperties;
176+
model.imports.push(...additionalProperties.imports);
177+
model.default = getModelDefault(definition, model);
178+
return model;
164179
}
165-
return model;
166180
}
167181

168182
// If the schema has a type than it can be a basic or generic type.

test/__snapshots__/index.spec.ts.snap

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3650,6 +3650,9 @@ export { EnumWithExtensions } from './models/EnumWithExtensions';
36503650
export { EnumWithNumbers } from './models/EnumWithNumbers';
36513651
export { EnumWithStrings } from './models/EnumWithStrings';
36523652
export type { File } from './models/File';
3653+
export type { FreeFormObjectWithAdditionalPropertiesEqEmptyObject } from './models/FreeFormObjectWithAdditionalPropertiesEqEmptyObject';
3654+
export type { FreeFormObjectWithAdditionalPropertiesEqTrue } from './models/FreeFormObjectWithAdditionalPropertiesEqTrue';
3655+
export type { FreeFormObjectWithoutAdditionalProperties } from './models/FreeFormObjectWithoutAdditionalProperties';
36533656
export type { ModelCircle } from './models/ModelCircle';
36543657
export type { ModelSquare } from './models/ModelSquare';
36553658
export type { ModelThatExtends } from './models/ModelThatExtends';
@@ -3715,6 +3718,9 @@ export { $EnumWithExtensions } from './schemas/$EnumWithExtensions';
37153718
export { $EnumWithNumbers } from './schemas/$EnumWithNumbers';
37163719
export { $EnumWithStrings } from './schemas/$EnumWithStrings';
37173720
export { $File } from './schemas/$File';
3721+
export { $FreeFormObjectWithAdditionalPropertiesEqEmptyObject } from './schemas/$FreeFormObjectWithAdditionalPropertiesEqEmptyObject';
3722+
export { $FreeFormObjectWithAdditionalPropertiesEqTrue } from './schemas/$FreeFormObjectWithAdditionalPropertiesEqTrue';
3723+
export { $FreeFormObjectWithoutAdditionalProperties } from './schemas/$FreeFormObjectWithoutAdditionalProperties';
37183724
export { $ModelCircle } from './schemas/$ModelCircle';
37193725
export { $ModelSquare } from './schemas/$ModelSquare';
37203726
export { $ModelThatExtends } from './schemas/$ModelThatExtends';
@@ -4341,6 +4347,42 @@ export type File = {
43414347
"
43424348
`;
43434349

4350+
exports[`v3 should generate: ./test/generated/v3/models/FreeFormObjectWithAdditionalPropertiesEqEmptyObject.ts 1`] = `
4351+
"/* istanbul ignore file */
4352+
/* tslint:disable */
4353+
/* eslint-disable */
4354+
4355+
/**
4356+
* This is a free-form object with additionalProperties: {}.
4357+
*/
4358+
export type FreeFormObjectWithAdditionalPropertiesEqEmptyObject = Record<string, any>;
4359+
"
4360+
`;
4361+
4362+
exports[`v3 should generate: ./test/generated/v3/models/FreeFormObjectWithAdditionalPropertiesEqTrue.ts 1`] = `
4363+
"/* istanbul ignore file */
4364+
/* tslint:disable */
4365+
/* eslint-disable */
4366+
4367+
/**
4368+
* This is a free-form object with additionalProperties: true.
4369+
*/
4370+
export type FreeFormObjectWithAdditionalPropertiesEqTrue = Record<string, any>;
4371+
"
4372+
`;
4373+
4374+
exports[`v3 should generate: ./test/generated/v3/models/FreeFormObjectWithoutAdditionalProperties.ts 1`] = `
4375+
"/* istanbul ignore file */
4376+
/* tslint:disable */
4377+
/* eslint-disable */
4378+
4379+
/**
4380+
* This is a free-form object without additionalProperties.
4381+
*/
4382+
export type FreeFormObjectWithoutAdditionalProperties = Record<string, any>;
4383+
"
4384+
`;
4385+
43444386
exports[`v3 should generate: ./test/generated/v3/models/ModelCircle.ts 1`] = `
43454387
"/* istanbul ignore file */
43464388
/* tslint:disable */
@@ -5522,6 +5564,48 @@ export const $File = {
55225564
"
55235565
`;
55245566

5567+
exports[`v3 should generate: ./test/generated/v3/schemas/$FreeFormObjectWithAdditionalPropertiesEqEmptyObject.ts 1`] = `
5568+
"/* istanbul ignore file */
5569+
/* tslint:disable */
5570+
/* eslint-disable */
5571+
export const $FreeFormObjectWithAdditionalPropertiesEqEmptyObject = {
5572+
type: 'dictionary',
5573+
contains: {
5574+
properties: {
5575+
},
5576+
},
5577+
} as const;
5578+
"
5579+
`;
5580+
5581+
exports[`v3 should generate: ./test/generated/v3/schemas/$FreeFormObjectWithAdditionalPropertiesEqTrue.ts 1`] = `
5582+
"/* istanbul ignore file */
5583+
/* tslint:disable */
5584+
/* eslint-disable */
5585+
export const $FreeFormObjectWithAdditionalPropertiesEqTrue = {
5586+
type: 'dictionary',
5587+
contains: {
5588+
properties: {
5589+
},
5590+
},
5591+
} as const;
5592+
"
5593+
`;
5594+
5595+
exports[`v3 should generate: ./test/generated/v3/schemas/$FreeFormObjectWithoutAdditionalProperties.ts 1`] = `
5596+
"/* istanbul ignore file */
5597+
/* tslint:disable */
5598+
/* eslint-disable */
5599+
export const $FreeFormObjectWithoutAdditionalProperties = {
5600+
type: 'dictionary',
5601+
contains: {
5602+
properties: {
5603+
},
5604+
},
5605+
} as const;
5606+
"
5607+
`;
5608+
55255609
exports[`v3 should generate: ./test/generated/v3/schemas/$ModelCircle.ts 1`] = `
55265610
"/* istanbul ignore file */
55275611
/* tslint:disable */
@@ -7160,14 +7244,14 @@ export class TypesService {
71607244
*/
71617245
public static types(
71627246
parameterArray: Array<string> | null,
7163-
parameterDictionary: any,
7247+
parameterDictionary: Record<string, any> | null,
71647248
parameterEnum: 'Success' | 'Warning' | 'Error' | null,
71657249
parameterNumber: number = 123,
71667250
parameterString: string | null = 'default',
71677251
parameterBoolean: boolean | null = true,
7168-
parameterObject: any = null,
7252+
parameterObject: Record<string, any> | null = null,
71697253
id?: number,
7170-
): CancelablePromise<number | string | boolean | any> {
7254+
): CancelablePromise<number | string | boolean | Record<string, any>> {
71717255
return __request(OpenAPI, {
71727256
method: 'GET',
71737257
url: '/api/v{api-version}/types',

test/spec/v3.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,6 +2531,20 @@
25312531
}
25322532
}
25332533
}
2534+
},
2535+
"FreeFormObjectWithoutAdditionalProperties": {
2536+
"description": "This is a free-form object without additionalProperties.",
2537+
"type": "object"
2538+
},
2539+
"FreeFormObjectWithAdditionalPropertiesEqTrue": {
2540+
"description": "This is a free-form object with additionalProperties: true.",
2541+
"type": "object",
2542+
"additionalProperties": true
2543+
},
2544+
"FreeFormObjectWithAdditionalPropertiesEqEmptyObject": {
2545+
"description": "This is a free-form object with additionalProperties: {}.",
2546+
"type": "object",
2547+
"additionalProperties": {}
25342548
}
25352549
}
25362550
}

0 commit comments

Comments
 (0)