Skip to content

Commit

Permalink
feat: improve with reservedWords
Browse files Browse the repository at this point in the history
  • Loading branch information
GregoryMerlet committed Nov 27, 2024
1 parent eabc989 commit 9c7fcfa
Show file tree
Hide file tree
Showing 19 changed files with 278 additions and 82 deletions.
2 changes: 2 additions & 0 deletions docs/generators/typescript-nestjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@ These options may be applied as additional-properties (cli) or configOptions (pl
<li>float</li>
<li>for</li>
<li>formParams</li>
<li>from</li>
<li>function</li>
<li>goto</li>
<li>headerParams</li>
<li>headers</li>
<li>if</li>
<li>implements</li>
<li>import</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package org.openapitools.codegen.languages;

import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import lombok.Getter;
import lombok.Setter;
import org.openapitools.codegen.*;
Expand Down Expand Up @@ -88,6 +90,8 @@ public TypeScriptNestjsClientCodegen() {
apiPackage = "api";
modelPackage = "model";

reservedWords.addAll(Arrays.asList("from", "headers"));

this.cliOptions.add(new CliOption(NPM_REPOSITORY,
"Use this property to set an url your private npmRepo in the package.json"));
this.cliOptions.add(CliOption.newBoolean(WITH_INTERFACES,
Expand Down Expand Up @@ -265,6 +269,34 @@ private boolean isLanguageGenericType(String type) {
return false;
}

@Override
public List<CodegenParameter> fromRequestBodyToFormParameters(RequestBody body, Set<String> imports) {
List<CodegenParameter> superParams = super.fromRequestBodyToFormParameters(body, imports);
List<CodegenParameter> extendedParams = new ArrayList<CodegenParameter>();
for (CodegenParameter cp : superParams) {
extendedParams.add(new ExtendedCodegenParameter(cp));
}
return extendedParams;
}

@Override
public ExtendedCodegenParameter fromParameter(Parameter parameter, Set<String> imports) {
CodegenParameter cp = super.fromParameter(parameter, imports);
return new ExtendedCodegenParameter(cp);
}

@Override
public CodegenParameter fromFormProperty(String name, Schema propertySchema, Set<String> imports) {
CodegenParameter cp = super.fromFormProperty(name, propertySchema, imports);
return new ExtendedCodegenParameter(cp);
}

@Override
public CodegenParameter fromRequestBody(RequestBody body, Set<String> imports, String bodyParameterName) {
CodegenParameter cp = super.fromRequestBody(body, imports, bodyParameterName);
return new ExtendedCodegenParameter(cp);
}

@Override
public void postProcessParameter(CodegenParameter parameter) {
super.postProcessParameter(parameter);
Expand Down Expand Up @@ -327,6 +359,12 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap operations, L

// Overwrite path to TypeScript template string, after applying everything we just did.
op.path = pathBuffer.toString();

for (CodegenParameter cpParam : op.allParams) {
ExtendedCodegenParameter param = (ExtendedCodegenParameter) cpParam;

param.hasSanitizedName = !param.baseName.equals(param.paramName);
}
}

operations.put("hasSomeFormParams", hasSomeFormParams);
Expand Down Expand Up @@ -482,6 +520,126 @@ public String removeModelPrefixSuffix(String name) {
return result;
}

public class ExtendedCodegenParameter extends CodegenParameter {
public boolean hasSanitizedName = false;

public ExtendedCodegenParameter(CodegenParameter cp) {
super();

this.isFormParam = cp.isFormParam;
this.isQueryParam = cp.isQueryParam;
this.isPathParam = cp.isPathParam;
this.isHeaderParam = cp.isHeaderParam;
this.isCookieParam = cp.isCookieParam;
this.isBodyParam = cp.isBodyParam;
this.isContainer = cp.isContainer;
this.isCollectionFormatMulti = cp.isCollectionFormatMulti;
this.isPrimitiveType = cp.isPrimitiveType;
this.isModel = cp.isModel;
this.isExplode = cp.isExplode;
this.baseName = cp.baseName;
this.paramName = cp.paramName;
this.dataType = cp.dataType;
this.datatypeWithEnum = cp.datatypeWithEnum;
this.dataFormat = cp.dataFormat;
this.contentType = cp.contentType;
this.collectionFormat = cp.collectionFormat;
this.description = cp.description;
this.unescapedDescription = cp.unescapedDescription;
this.baseType = cp.baseType;
this.defaultValue = cp.defaultValue;
this.enumName = cp.enumName;
this.style = cp.style;
this.nameInLowerCase = cp.nameInLowerCase;
this.example = cp.example;
this.jsonSchema = cp.jsonSchema;
this.isString = cp.isString;
this.isNumeric = cp.isNumeric;
this.isInteger = cp.isInteger;
this.isLong = cp.isLong;
this.isNumber = cp.isNumber;
this.isFloat = cp.isFloat;
this.isDouble = cp.isDouble;
this.isDecimal = cp.isDecimal;
this.isByteArray = cp.isByteArray;
this.isBinary = cp.isBinary;
this.isBoolean = cp.isBoolean;
this.isDate = cp.isDate;
this.isDateTime = cp.isDateTime;
this.isUuid = cp.isUuid;
this.isUri = cp.isUri;
this.isEmail = cp.isEmail;
this.isFreeFormObject = cp.isFreeFormObject;
this.isAnyType = cp.isAnyType;
this.isArray = cp.isArray;
this.isMap = cp.isMap;
this.isFile = cp.isFile;
this.isEnum = cp.isEnum;
this.isEnumRef = cp.isEnumRef;
this._enum = cp._enum;
this.allowableValues = cp.allowableValues;
this.items = cp.items;
this.additionalProperties = cp.additionalProperties;
this.vars = cp.vars;
this.requiredVars = cp.requiredVars;
this.mostInnerItems = cp.mostInnerItems;
this.vendorExtensions = cp.vendorExtensions;
this.hasValidation = cp.hasValidation;
this.isNullable = cp.isNullable;
this.required = cp.required;
this.maximum = cp.maximum;
this.exclusiveMaximum = cp.exclusiveMaximum;
this.minimum = cp.minimum;
this.exclusiveMinimum = cp.exclusiveMinimum;
this.maxLength = cp.maxLength;
this.minLength = cp.minLength;
this.pattern = cp.pattern;
this.maxItems = cp.maxItems;
this.minItems = cp.minItems;
this.uniqueItems = cp.uniqueItems;
this.multipleOf = cp.multipleOf;
this.setHasVars(cp.getHasVars());
this.setHasRequired(cp.getHasRequired());
this.setMaxProperties(cp.getMaxProperties());
this.setMinProperties(cp.getMinProperties());
}

@Override
public ExtendedCodegenParameter copy() {
CodegenParameter superCopy = super.copy();
ExtendedCodegenParameter output = new ExtendedCodegenParameter(superCopy);
output.hasSanitizedName = this.hasSanitizedName;
return output;
}

@Override
public boolean equals(Object o) {
if (o == null)
return false;

if (this.getClass() != o.getClass())
return false;

boolean result = super.equals(o);
ExtendedCodegenParameter that = (ExtendedCodegenParameter) o;
return result && hasSanitizedName == that.hasSanitizedName;
}

@Override
public int hashCode() {
int superHash = super.hashCode();
return Objects.hash(superHash, hasSanitizedName);
}

@Override
public String toString() {
String superString = super.toString();
final StringBuilder sb = new StringBuilder(superString);
sb.append(", hasSanitizedName=").append(hasSanitizedName);
return sb.toString();
}
}

/**
* Validates that the given string value only contains '-', '.' and alpha numeric characters.
* Throws an IllegalArgumentException, if the string contains any other characters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export interface {{classname}}{{operationIdCamelCase}}Request {
* @type {{=<% %>=}}{<%&dataType%>}<%={{ }}=%>
* @memberof {{classname}}{{operationIdCamelCase}}
*/
readonly '{{paramName}}'{{^required}}?{{/required}}: {{{dataType}}}
readonly {{#hasSanitizedName}}'{{{baseName}}}'{{/hasSanitizedName}}{{^hasSanitizedName}}{{{paramName}}}{{/hasSanitizedName}}{{^required}}?{{/required}}: {{{dataType}}}
{{^-last}}

{{/-last}}
Expand Down Expand Up @@ -102,13 +102,23 @@ export class {{classname}} {
public {{nickname}}({{#allParams}}{{^isConstEnumParam}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/isConstEnumParam}}{{/allParams}}): Observable<AxiosResponse<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>>;
public {{nickname}}({{#allParams}}{{^isConstEnumParam}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/isConstEnumParam}}{{/allParams}}): Observable<any> {
{{/useSingleRequestParameter}}
{{#allParams.0}}
{{#useSingleRequestParameter}}
const {
{{#allParams}}
{{#hasSanitizedName}}'{{{baseName}}}': {{/hasSanitizedName}}{{paramName}},
{{/allParams}}
} = requestParameters;

{{/useSingleRequestParameter}}
{{/allParams.0}}
{{#allParams}}
{{#required}}
{{#isConstEnumParam}}
let {{paramName}} = {{{dataType}}};
{{/isConstEnumParam}}
{{^isConstEnumParam}}
if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} === null || {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} === undefined) {
if ({{paramName}} === null || {{paramName}} === undefined) {
throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.');
}

Expand All @@ -119,24 +129,24 @@ export class {{classname}} {
let queryParameters = new URLSearchParams();
{{#queryParams}}
{{#isArray}}
if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) {
if ({{paramName}}) {
{{#isCollectionFormatMulti}}
{{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.forEach((element) => {
{{paramName}}.forEach((element) => {
queryParameters.append('{{baseName}}', <any>element);
})
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
queryParameters['{{baseName}}'] = {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}']);
queryParameters['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']);
{{/isCollectionFormatMulti}}
}
{{/isArray}}
{{^isArray}}
if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined && {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== null) {
if ({{paramName}} !== undefined && {{paramName}} !== null) {
{{#isDateTime}}
queryParameters.append('{{baseName}}', (<any>{{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}).toISOString());
queryParameters.append('{{baseName}}', (<any>{{paramName}}).toISOString());
{{/isDateTime}}
{{^isDateTime}}
queryParameters.append('{{baseName}}', <any>{{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}});
queryParameters.append('{{baseName}}', <any>{{paramName}});
{{/isDateTime}}
}
{{/isArray}}
Expand All @@ -146,13 +156,13 @@ export class {{classname}} {
let headers = {...this.defaultHeaders};
{{#headerParams}}
{{#isArray}}
if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) {
headers['{{baseName}}'] = {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}']);
if ({{paramName}}) {
headers['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']);
}
{{/isArray}}
{{^isArray}}
if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined && {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== null) {
headers['{{baseName}}'] = String({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}});
if ({{paramName}} !== undefined && {{paramName}} !== null) {
headers['{{baseName}}'] = String({{paramName}});
}
{{/isArray}}
{{/headerParams}}
Expand Down Expand Up @@ -246,20 +256,20 @@ export class {{classname}} {
{{#formParams}}

{{#isArray}}
if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) {
if ({{paramName}}) {
{{#isCollectionFormatMulti}}
{{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.forEach((element) => {
{{paramName}}.forEach((element) => {
formParams!.append('{{baseName}}', <any>element);
})
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
formParams!.append('{{baseName}}', {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}']));
formParams!.append('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']));
{{/isCollectionFormatMulti}}
}
{{/isArray}}
{{^isArray}}
if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined) {
formParams!.append('{{baseName}}', <any>{{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}});
if ({{paramName}} !== undefined) {
formParams!.append('{{baseName}}', <any>{{paramName}});
}
{{/isArray}}
{{/formParams}}
Expand All @@ -272,7 +282,7 @@ export class {{classname}} {
}

return this.httpClient.{{httpMethod}}{{^isResponseFile}}<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>{{/isResponseFile}}(`${this.basePath}{{{path}}}`,{{#isBodyAllowed}}
{{#bodyParam}}{{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams!.toString() : formParams!{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}},{{/isBodyAllowed}}
{{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams!.toString() : formParams!{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}},{{/isBodyAllowed}}
{
{{#hasQueryParams}}
params: queryParameters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ export interface {{classname}}{{#allParents}}{{#-first}} extends {{/-first}}{{{.
* {{{.}}}
*/
{{/description}}
{{#isReadOnly}}readonly {{/isReadOnly}}'{{{name}}}'{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}};
{{#isReadOnly}}readonly {{/isReadOnly}}{{#hasSanitizedName}}'{{{baseName}}}'{{/hasSanitizedName}}{{^hasSanitizedName}}{{{name}}}{{/hasSanitizedName}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}};
{{/vars}}
}{{>modelGenericEnums}}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface {{classname}} { {{>modelGenericAdditionalProperties}}
* {{{.}}}
*/
{{/description}}
'{{name}}'{{^required}}?{{/required}}: {{#discriminatorValue}}'{{.}}'{{/discriminatorValue}}{{^discriminatorValue}}{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{/discriminatorValue}}{{#isNullable}} | null{{/isNullable}};
{{#hasSanitizedName}}'{{{baseName}}}'{{/hasSanitizedName}}{{^hasSanitizedName}}{{{name}}}{{/hasSanitizedName}}{{^required}}?{{/required}}: {{#discriminatorValue}}'{{.}}'{{/discriminatorValue}}{{^discriminatorValue}}{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{/discriminatorValue}}{{#isNullable}} | null{{/isNullable}};
{{/allVars}}
}
{{>modelGenericEnums}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ paths:
description: ''
operationId: testReservedParamNames
parameters:
- name: notReserved
in: query
description: Should not be treated as a reserved param name
required: true
schema:
type: string
- name: from
in: query
description: Might conflict with rxjs import
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
* Describes the result of uploading an image resource
*/
export interface ApiResponse {
'code'?: number;
'type'?: string;
'message'?: string;
code?: number;
type?: string;
message?: string;
}

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* A category for a pet
*/
export interface Category {
'id'?: number;
'name'?: string;
id?: number;
name?: string;
}

Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
* An order for a pets from the pet store
*/
export interface Order {
'id'?: number;
'petId'?: number;
'quantity'?: number;
'shipDate'?: string;
id?: number;
petId?: number;
quantity?: number;
shipDate?: string;
/**
* Order Status
*/
'status'?: Order.StatusEnum;
'complete'?: boolean;
status?: Order.StatusEnum;
complete?: boolean;
}
export namespace Order {
export type StatusEnum = 'placed' | 'approved' | 'delivered';
Expand Down
Loading

0 comments on commit 9c7fcfa

Please sign in to comment.