Skip to content

Commit bc5c24b

Browse files
authored
feat: render patternProperties for TS class and interface (#270)
1 parent dc6971d commit bc5c24b

File tree

6 files changed

+48
-8
lines changed

6 files changed

+48
-8
lines changed

src/generators/typescript/TypeScriptRenderer.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ ${lines.map(line => ` * ${line}`).join('\n')}
107107
content.push(additionalProperty);
108108
}
109109

110+
if (this.model.patternProperties !== undefined) {
111+
for (const [pattern, patternModel] of Object.entries(this.model.patternProperties)) {
112+
const propertyName = getUniquePropertyName(this.model, `${pattern}${DefaultPropertyNames.patternProperties}`);
113+
const renderedPatternProperty = await this.runPropertyPreset(propertyName, patternModel, PropertyType.patternProperties);
114+
content.push(renderedPatternProperty);
115+
}
116+
}
117+
110118
return this.renderBlock(content);
111119
}
112120

@@ -118,6 +126,7 @@ ${lines.map(line => ` * ${line}`).join('\n')}
118126
signature = this.renderTypeSignature(property, { isRequired: this.model.isRequired(propertyName) });
119127
return `${name}${signature};`;
120128
case PropertyType.additionalProperty:
129+
case PropertyType.patternProperties:
121130
signature = this.renderType(property);
122131
return `${name}?: Map<String, ${signature}>;`;
123132
default:

src/generators/typescript/renderers/ClassRenderer.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ ${this.indent(this.renderBlock(content, 2))}
4343
content.push(this.renderBlock([getter, setter]));
4444
}
4545

46+
if (this.model.patternProperties !== undefined) {
47+
for (const [pattern, patternModel] of Object.entries(this.model.patternProperties)) {
48+
const propertyName = getUniquePropertyName(this.model, `${pattern}${DefaultPropertyNames.patternProperties}`);
49+
const getter = await this.runGetterPreset(propertyName, patternModel, PropertyType.patternProperties);
50+
const setter = await this.runSetterPreset(propertyName, patternModel, PropertyType.patternProperties);
51+
content.push(this.renderBlock([getter, setter]));
52+
}
53+
}
54+
4655
return this.renderBlock(content, 2);
4756
}
4857

@@ -86,9 +95,9 @@ ${renderer.indent(renderer.renderBlock(assignments))}
8695
let signature = '';
8796
if (type === PropertyType.property) {
8897
signature = renderer.renderTypeSignature(property, { orUndefined: !isRequired });
89-
} else if (type === PropertyType.additionalProperty) {
90-
const additionalPropertyType = renderer.renderType(property);
91-
signature = `: Map<String, ${additionalPropertyType}> | undefined`;
98+
} else if (type === PropertyType.additionalProperty || type === PropertyType.patternProperties) {
99+
const mapType = renderer.renderType(property);
100+
signature = `: Map<String, ${mapType}> | undefined`;
92101
}
93102
return `get ${propertyName}()${signature} { return this._${propertyName}; }`;
94103
},
@@ -98,9 +107,9 @@ ${renderer.indent(renderer.renderBlock(assignments))}
98107
let signature = '';
99108
if (type === PropertyType.property) {
100109
signature = renderer.renderTypeSignature(property, { orUndefined: !isRequired });
101-
} else if (type === PropertyType.additionalProperty) {
102-
const additionalPropertyType = renderer.renderType(property);
103-
signature = `: Map<String, ${additionalPropertyType}> | undefined`;
110+
} else if (type === PropertyType.additionalProperty || type === PropertyType.patternProperties) {
111+
const mapType = renderer.renderType(property);
112+
signature = `: Map<String, ${mapType}> | undefined`;
104113
}
105114
return `set ${propertyName}(${propertyName}${signature}) { this._${propertyName} = ${propertyName}; }`;
106115
},

src/helpers/NameHelpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { CommonModel } from 'models';
44
* Default property names for different aspects of the common model
55
*/
66
export enum DefaultPropertyNames {
7-
additionalProperties = 'additionalProperties'
7+
additionalProperties = 'additionalProperties',
8+
patternProperties = 'PatternProperties'
89
}
910

1011
/**

src/models/Preset.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export interface CommonPreset<R extends AbstractRenderer, O extends object = any
1818

1919
export enum PropertyType {
2020
property,
21-
additionalProperty
21+
additionalProperty,
22+
patternProperties
2223
}
2324
export interface PropertyArgs {
2425
propertyName: string;

test/blackbox/docs/dummy.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
"$ref": "#/definitions/dummyObject"
4848
}
4949
},
50+
"patternProperties": {
51+
"^S(.?*)pattern&": {
52+
"type": "string"
53+
}
54+
},
5055
"definitions": {
5156
"dummyInfo": {
5257
"type": "object",

test/generators/typescript/TypeScriptGenerator.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ describe('TypeScriptGenerator', () => {
2020
tuple_type_with_additional_items: { type: 'array', items: [{ type: 'string' }, { type: 'number' }], additionalItems: true },
2121
array_type: { type: 'array', items: { type: 'string' } },
2222
},
23+
patternProperties: {
24+
'^S(.?*)test&': {
25+
type: 'string'
26+
}
27+
},
2328
required: ['street_name', 'city', 'state', 'house_number', 'array_type'],
2429
};
2530
const expected = `export class Address {
@@ -33,6 +38,7 @@ describe('TypeScriptGenerator', () => {
3338
private _tupleTypeWithAdditionalItems?: [string, number, ...(object | string | number | Array<unknown> | boolean | null | number)[]];
3439
private _arrayType: Array<string>;
3540
private _additionalProperties?: Map<String, object | string | number | Array<unknown> | boolean | null | number>;
41+
private _sTestPatternProperties?: Map<String, string>;
3642
3743
constructor(input: {
3844
streetName: string,
@@ -85,6 +91,9 @@ describe('TypeScriptGenerator', () => {
8591
8692
get additionalProperties(): Map<String, object | string | number | Array<unknown> | boolean | null | number> | undefined { return this._additionalProperties; }
8793
set additionalProperties(additionalProperties: Map<String, object | string | number | Array<unknown> | boolean | null | number> | undefined) { this._additionalProperties = additionalProperties; }
94+
95+
get sTestPatternProperties(): Map<String, string> | undefined { return this._sTestPatternProperties; }
96+
set sTestPatternProperties(sTestPatternProperties: Map<String, string> | undefined) { this._sTestPatternProperties = sTestPatternProperties; }
8897
}`;
8998

9099
const inputModel = await generator.process(doc);
@@ -160,6 +169,11 @@ ${content}`;
160169
tuple_type_with_additional_items: { type: 'array', items: [{ type: 'string' }, { type: 'number' }], additionalItems: true },
161170
array_type: { type: 'array', items: { type: 'string' } },
162171
},
172+
patternProperties: {
173+
'^S(.?*)test&': {
174+
type: 'string'
175+
}
176+
},
163177
required: ['street_name', 'city', 'state', 'house_number', 'array_type'],
164178
};
165179
const expected = `export interface Address {
@@ -173,6 +187,7 @@ ${content}`;
173187
tupleTypeWithAdditionalItems?: [string, number, ...(object | string | number | Array<unknown> | boolean | null | number)[]];
174188
arrayType: Array<string>;
175189
additionalProperties?: Map<String, object | string | number | Array<unknown> | boolean | null | number>;
190+
sTestPatternProperties?: Map<String, string>;
176191
}`;
177192

178193
const interfaceGenerator = new TypeScriptGenerator({modelType: 'interface'});

0 commit comments

Comments
 (0)