Skip to content

[TypeScript] add an option to determine property naming convention #1965

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,9 @@ public class CodegenConstants {
public static final String OPTIONAL_PROJECT_GUID = "packageGuid";
public static final String OPTIONAL_PROJECT_GUID_DESC = "The GUID that will be associated with the C# project";

public static final String MODEL_PROPERTY_NAMING = "modelPropertyNaming";
public static final String MODEL_PROPERTY_NAMING_DESC = "Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name";

public static enum MODEL_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, original}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {

protected String modelPropertyNaming= "camelCase";

public AbstractTypeScriptClientCodegen() {
super();
supportsInheritance = true;
Expand Down Expand Up @@ -50,8 +52,21 @@ public AbstractTypeScriptClientCodegen() {
typeMapping.put("DateTime", "Date");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
typeMapping.put("binary", "string");

cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase"));


}

@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
}
}


@Override
public CodegenType getTag() {
Expand All @@ -74,7 +89,7 @@ public String modelFileFolder() {
}

@Override
public String toVarName(String name) {
public String toParamName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.

Expand All @@ -94,9 +109,9 @@ public String toVarName(String name) {
}

@Override
public String toParamName(String name) {
public String toVarName(String name) {
// should be the same as variable name
return toVarName(name);
return getNameUsingModelPropertyNaming(name);
}

@Override
Expand Down Expand Up @@ -146,19 +161,47 @@ public String getSwaggerType(Property p) {
return type;
}

@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}

// method name cannot use reserved keyword, e.g. return
// append _ at the beginning, e.g. _return
if (reservedWords.contains(operationId)) {
return escapeReservedWord(camelize(sanitizeName(operationId), true));
}

return camelize(sanitizeName(operationId), true);
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}

// method name cannot use reserved keyword, e.g. return
// append _ at the beginning, e.g. _return
if (reservedWords.contains(operationId)) {
return escapeReservedWord(camelize(sanitizeName(operationId), true));
}

return camelize(sanitizeName(operationId), true);
}

public void setModelPropertyNaming(String naming) {
if ("original".equals(naming) || "camelCase".equals(naming) ||
"PascalCase".equals(naming) || "snake_case".equals(naming)) {
this.modelPropertyNaming = naming;
} else {
throw new IllegalArgumentException("Invalid model property naming '" +
naming + "'. Must be 'original', 'camelCase', " +
"'PascalCase' or 'snake_case'");
}
}

public String getModelPropertyNaming() {
return this.modelPropertyNaming;
}

public String getNameUsingModelPropertyNaming(String name) {
switch (CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.valueOf(getModelPropertyNaming())) {
case original: return name;
case camelCase: return camelize(name, true);
case PascalCase: return camelize(name);
case snake_case: return underscore(name);
default: throw new IllegalArgumentException("Invalid model property naming '" +
name + "'. Must be 'original', 'camelCase', " +
"'PascalCase' or 'snake_case'");
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public class TypeScriptAngularClientOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";

@Override
public String getLanguage() {
Expand All @@ -20,6 +21,7 @@ public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public class TypeScriptNodeClientOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";

@Override
public String getLanguage() {
Expand All @@ -20,6 +21,7 @@ public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(TypeScriptAngularClientOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
clientCodegen.setModelPropertyNaming(TypeScriptAngularClientOptionsProvider.MODEL_PROPERTY_NAMING_VALUE);
times = 1;
}};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(TypeScriptNodeClientOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
clientCodegen.setModelPropertyNaming(TypeScriptNodeClientOptionsProvider.MODEL_PROPERTY_NAMING_VALUE);
times = 1;
}};
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

Binary file not shown.
58 changes: 58 additions & 0 deletions samples/client/petstore/typescript-angular/API/Client/PetApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,64 @@ namespace API.Client {
httpRequestParams = this.extendObj(httpRequestParams, extraHttpRequestParams);
}

return this.$http(httpRequestParams);
}
/**
* Fake endpoint to test byte array return by &#39;Find pet by ID&#39;
* Returns a pet when ID &lt; 10. ID &gt; 10 or nonintegers will simulate API error conditions
* @param petId ID of pet that needs to be fetched
*/
public getPetByIdWithByteArray (petId: number, extraHttpRequestParams?: any ) : ng.IHttpPromise<string> {
const path = this.basePath + '/pet/{petId}?testing_byte_array=true'
.replace('{' + 'petId' + '}', String(petId));

let queryParameters: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
// verify required parameter 'petId' is set
if (!petId) {
throw new Error('Missing required parameter petId when calling getPetByIdWithByteArray');
}
let httpRequestParams: any = {
method: 'GET',
url: path,
json: true,


params: queryParameters,
headers: headerParams
};

if (extraHttpRequestParams) {
httpRequestParams = this.extendObj(httpRequestParams, extraHttpRequestParams);
}

return this.$http(httpRequestParams);
}
/**
* Fake endpoint to test byte array in body parameter for adding a new pet to the store
*
* @param body Pet object in the form of byte array
*/
public addPetUsingByteArray (body?: string, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> {
const path = this.basePath + '/pet?testing_byte_array=true';

let queryParameters: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
let httpRequestParams: any = {
method: 'POST',
url: path,
json: true,
data: body,


params: queryParameters,
headers: headerParams
};

if (extraHttpRequestParams) {
httpRequestParams = this.extendObj(httpRequestParams, extraHttpRequestParams);
}

return this.$http(httpRequestParams);
}
}
Expand Down
107 changes: 107 additions & 0 deletions samples/client/petstore/typescript-node/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,113 @@ export class PetApi {
}
});

return deferred.promise;
}
/**
* Fake endpoint to test byte array return by &#39;Find pet by ID&#39;
* Returns a pet when ID &lt; 10. ID &gt; 10 or nonintegers will simulate API error conditions
* @param petId ID of pet that needs to be fetched
*/
public getPetByIdWithByteArray (petId: number) : Promise<{ response: http.ClientResponse; body: string; }> {
const path = this.basePath + '/pet/{petId}?testing_byte_array=true'
.replace('{' + 'petId' + '}', String(petId));
let queryParameters: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
let formParams: any = {};


// verify required parameter 'petId' is set
if (!petId) {
throw new Error('Missing required parameter petId when calling getPetByIdWithByteArray');
}

let useFormData = false;

let deferred = promise.defer<{ response: http.ClientResponse; body: string; }>();

let requestOptions: request.Options = {
method: 'GET',
qs: queryParameters,
headers: headerParams,
uri: path,
json: true,
}

this.authentications.api_key.applyToRequest(requestOptions);

this.authentications.default.applyToRequest(requestOptions);

if (Object.keys(formParams).length) {
if (useFormData) {
(<any>requestOptions).formData = formParams;
} else {
requestOptions.form = formParams;
}
}

request(requestOptions, (error, response, body) => {
if (error) {
deferred.reject(error);
} else {
if (response.statusCode >= 200 && response.statusCode <= 299) {
deferred.resolve({ response: response, body: body });
} else {
deferred.reject({ response: response, body: body });
}
}
});

return deferred.promise;
}
/**
* Fake endpoint to test byte array in body parameter for adding a new pet to the store
*
* @param body Pet object in the form of byte array
*/
public addPetUsingByteArray (body?: string) : Promise<{ response: http.ClientResponse; body?: any; }> {
const path = this.basePath + '/pet?testing_byte_array=true';
let queryParameters: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
let formParams: any = {};


let useFormData = false;

let deferred = promise.defer<{ response: http.ClientResponse; body?: any; }>();

let requestOptions: request.Options = {
method: 'POST',
qs: queryParameters,
headers: headerParams,
uri: path,
json: true,
body: body,
}

this.authentications.petstore_auth.applyToRequest(requestOptions);

this.authentications.default.applyToRequest(requestOptions);

if (Object.keys(formParams).length) {
if (useFormData) {
(<any>requestOptions).formData = formParams;
} else {
requestOptions.form = formParams;
}
}

request(requestOptions, (error, response, body) => {
if (error) {
deferred.reject(error);
} else {
if (response.statusCode >= 200 && response.statusCode <= 299) {
deferred.resolve({ response: response, body: body });
} else {
deferred.reject({ response: response, body: body });
}
}
});

return deferred.promise;
}
}
Expand Down