Skip to content

Commit

Permalink
[typescript-fetch] Allow to generate client without runtime checks (O…
Browse files Browse the repository at this point in the history
…penAPITools#7894)

* Add CLI options to remove runtime checks (serialization/deserialization).

* Update templates to support the new parameter

- Generates all the models in a same file to avoid import complexity
- Extract interfaces creator templates to reuse them

* Fix formatting and generate client examples

* Add documentation
  • Loading branch information
acote-coveo authored Nov 16, 2020
1 parent 54d6257 commit 36aba26
Show file tree
Hide file tree
Showing 42 changed files with 1,872 additions and 198 deletions.
9 changes: 9 additions & 0 deletions bin/configs/typescript-fetch-without-runtime-checks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
generatorName: typescript-fetch
outputDir: samples/client/petstore/typescript-fetch/builds/without-runtime-checks
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
additionalProperties:
npmVersion: 1.0.0
npmName: '@openapitools/typescript-fetch-petstore'
npmRepository: https://skimdb.npmjs.com/registry
withoutRuntimeChecks: true
snapshot: false
1 change: 1 addition & 0 deletions docs/generators/typescript-fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|typescriptThreePlus|Setting this property to true will generate TypeScript 3.6+ compatible code.| |false|
|useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |true|
|withInterfaces|Setting this property to true will generate interfaces next to the default class implementations.| |false|
|withoutRuntimeChecks|Setting this property to true will remove any runtime checks on the request and response payloads. Payloads will be casted to their expected types.| |false|

## IMPORT MAPPING

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
public static final String USE_SINGLE_REQUEST_PARAMETER = "useSingleRequestParameter";
public static final String PREFIX_PARAMETER_INTERFACES = "prefixParameterInterfaces";
public static final String TYPESCRIPT_THREE_PLUS = "typescriptThreePlus";
public static final String WITHOUT_RUNTIME_CHECKS = "withoutRuntimeChecks";

protected String npmRepository = null;
private boolean useSingleRequestParameter = true;
private boolean prefixParameterInterfaces = false;
protected boolean addedApiIndex = false;
protected boolean addedModelIndex = false;
protected boolean typescriptThreePlus = false;
protected boolean withoutRuntimeChecks = false;


public TypeScriptFetchClientCodegen() {
Expand All @@ -61,7 +63,7 @@ public TypeScriptFetchClientCodegen() {
embeddedTemplateDir = templateDir = "typescript-fetch";

this.apiTemplateFiles.put("apis.mustache", ".ts");
this.modelTemplateFiles.put("models.mustache", ".ts");

this.addExtraReservedWords();

typeMapping.put("date", "Date");
Expand All @@ -73,6 +75,7 @@ public TypeScriptFetchClientCodegen() {
this.cliOptions.add(new CliOption(CodegenConstants.USE_SINGLE_REQUEST_PARAMETER, CodegenConstants.USE_SINGLE_REQUEST_PARAMETER_DESC, SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.TRUE.toString()));
this.cliOptions.add(new CliOption(PREFIX_PARAMETER_INTERFACES, "Setting this property to true will generate parameter interface declarations prefixed with API class name to avoid name conflicts.", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
this.cliOptions.add(new CliOption(TYPESCRIPT_THREE_PLUS, "Setting this property to true will generate TypeScript 3.6+ compatible code.", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
this.cliOptions.add(new CliOption(WITHOUT_RUNTIME_CHECKS, "Setting this property to true will remove any runtime checks on the request and response payloads. Payloads will be casted to their expected types.", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
}

@Override
Expand Down Expand Up @@ -101,6 +104,14 @@ public void setTypescriptThreePlus(Boolean typescriptThreePlus) {
this.typescriptThreePlus = typescriptThreePlus;
}

public Boolean getWithoutRuntimeChecks(){
return withoutRuntimeChecks;
}

public void setWithoutRuntimeChecks(Boolean withoutRuntimeChecks){
this.withoutRuntimeChecks = withoutRuntimeChecks;
}

@Override
public void processOpts() {
super.processOpts();
Expand Down Expand Up @@ -135,6 +146,14 @@ public void processOpts() {
if (additionalProperties.containsKey(TYPESCRIPT_THREE_PLUS)) {
this.setTypescriptThreePlus(convertPropertyToBoolean(TYPESCRIPT_THREE_PLUS));
}

if (additionalProperties.containsKey(WITHOUT_RUNTIME_CHECKS)) {
this.setWithoutRuntimeChecks(convertPropertyToBoolean(WITHOUT_RUNTIME_CHECKS));
}

if(!withoutRuntimeChecks){
this.modelTemplateFiles.put("models.mustache", ".ts");
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import * as runtime from '../runtime';
import {
{{#imports}}
{{className}},
{{^withoutRuntimeChecks}}
{{className}}FromJSON,
{{className}}ToJSON,
{{/withoutRuntimeChecks}}
{{/imports}}
} from '../models';
{{/imports.0}}
Expand Down Expand Up @@ -242,7 +244,11 @@ export class {{classname}} extends runtime.BaseAPI {
formParams.append('{{baseName}}', requestParameters.{{paramName}} as any);
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{^withoutRuntimeChecks}}
formParams.append('{{baseName}}', new Blob([JSON.stringify({{{dataType}}}ToJSON(requestParameters.{{paramName}}))], { type: "application/json", }));
{{/withoutRuntimeChecks}}{{#withoutRuntimeChecks}}
formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters.{{paramName}})], { type: "application/json", }));
{{/withoutRuntimeChecks}}
{{/isPrimitiveType}}
}
Expand All @@ -257,11 +263,21 @@ export class {{classname}} extends runtime.BaseAPI {
{{#hasBodyParam}}
{{#bodyParam}}
{{#isContainer}}
{{^withoutRuntimeChecks}}
body: requestParameters.{{paramName}}{{#isArray}}{{#items}}{{^isPrimitiveType}}.map({{datatype}}ToJSON){{/isPrimitiveType}}{{/items}}{{/isArray}},
{{/withoutRuntimeChecks}}
{{#withoutRuntimeChecks}}
body: requestParameters.{{paramName}}{{#isArray}}{{#items}}{{^isPrimitiveType}}{{/isPrimitiveType}}{{/items}}{{/isArray}},
{{/withoutRuntimeChecks}}
{{/isContainer}}
{{^isContainer}}
{{^isPrimitiveType}}
{{^withoutRuntimeChecks}}
body: {{dataType}}ToJSON(requestParameters.{{paramName}}),
{{/withoutRuntimeChecks}}
{{#withoutRuntimeChecks}}
body: requestParameters.{{paramName}},
{{/withoutRuntimeChecks}}
{{/isPrimitiveType}}
{{#isPrimitiveType}}
body: requestParameters.{{paramName}} as any,
Expand Down Expand Up @@ -292,14 +308,14 @@ export class {{classname}} extends runtime.BaseAPI {
{{/returnTypeIsPrimitive}}
{{^returnTypeIsPrimitive}}
{{#isArray}}
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map({{returnBaseType}}FromJSON));
return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, (jsonValue) => jsonValue.map({{returnBaseType}}FromJSON){{/withoutRuntimeChecks}});
{{/isArray}}
{{^isArray}}
{{#isMap}}
return new runtime.JSONApiResponse(response, (jsonValue) => runtime.mapValues(jsonValue, {{returnBaseType}}FromJSON));
return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, (jsonValue) => runtime.mapValues(jsonValue, {{returnBaseType}}FromJSON){{/withoutRuntimeChecks}});
{{/isMap}}
{{^isMap}}
return new runtime.JSONApiResponse(response, (jsonValue) => {{returnBaseType}}FromJSON(jsonValue));
return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, (jsonValue) => {{returnBaseType}}FromJSON(jsonValue){{/withoutRuntimeChecks}});
{{/isMap}}
{{/isArray}}
{{/returnTypeIsPrimitive}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
/**
* {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}}
* @export
* @enum {string}
*/
export enum {{classname}} {
{{#allowableValues}}
{{#enumVars}}
{{{name}}} = {{{value}}}{{^-last}},{{/-last}}
{{/enumVars}}
{{/allowableValues}}
}
{{>modelEnumInterfaces}}

export function {{classname}}FromJSON(json: any): {{classname}} {
return {{classname}}FromJSONTyped(json, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}}
* @export
* @enum {string}
*/
export enum {{classname}} {
{{#allowableValues}}
{{#enumVars}}
{{{name}}} = {{{value}}}{{^-last}},{{/-last}}
{{/enumVars}}
{{/allowableValues}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,7 @@ import {
} from './';

{{/discriminator}}
/**
* {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}}
* @export
* @interface {{classname}}
*/
export interface {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{
{{#additionalPropertiesType}}
[key: string]: {{{additionalPropertiesType}}}{{#hasVars}} | any{{/hasVars}};
{{/additionalPropertiesType}}
{{#vars}}
/**
* {{#lambda.indented_star_4}}{{{unescapedDescription}}}{{/lambda.indented_star_4}}
* @type {{=<% %>=}}{<%&datatype%>}<%={{ }}=%>
* @memberof {{classname}}
*/
{{#isReadOnly}}readonly {{/isReadOnly}}{{name}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}};
{{/vars}}
}
{{>modelGenericInterfaces}}

export function {{classname}}FromJSON(json: any): {{classname}} {
return {{classname}}FromJSONTyped(json, false);
Expand Down Expand Up @@ -145,21 +128,3 @@ export function {{classname}}ToJSON(value?: {{classname}} | null): any {
{{/hasVars}}
}

{{#hasEnums}}
{{#vars}}
{{#isEnum}}
/**
* @export
* @enum {string}
*/
export enum {{classname}}{{enumName}} {
{{#allowableValues}}
{{#enumVars}}
{{{name}}} = {{{value}}}{{^-last}},{{/-last}}
{{/enumVars}}
{{/allowableValues}}
}
{{/isEnum}}
{{/vars}}

{{/hasEnums}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}}
* @export
* @interface {{classname}}
*/
export interface {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{
{{#additionalPropertiesType}}
[key: string]: {{{additionalPropertiesType}}}{{#hasVars}} | any{{/hasVars}};
{{/additionalPropertiesType}}
{{#vars}}
/**
* {{#lambda.indented_star_4}}{{{unescapedDescription}}}{{/lambda.indented_star_4}}
* @type {{=<% %>=}}{<%&datatype%>}<%={{ }}=%>
* @memberof {{classname}}
*/
{{#isReadOnly}}readonly {{/isReadOnly}}{{name}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}};
{{/vars}}
}{{#hasEnums}}

{{#vars}}
{{#isEnum}}
/**
* @export
* @enum {string}
*/
export enum {{classname}}{{enumName}} {
{{#allowableValues}}
{{#enumVars}}
{{{name}}} = {{{value}}}{{^-last}},{{/-last}}
{{/enumVars}}
{{/allowableValues}}
}{{/isEnum}}{{/vars}}{{/hasEnums}}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@ import {
} from './';

{{/hasImports}}
/**
* @type {{classname}}
* {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}}
* @export
*/
export type {{classname}} = {{#discriminator}}{{#mappedModels}}{ {{discriminator.propertyName}}: '{{mappingName}}' } & {{modelName}}{{^-last}} | {{/-last}}{{/mappedModels}}{{/discriminator}}{{^discriminator}}{{#oneOf}}{{{.}}}{{^-last}} | {{/-last}}{{/oneOf}}{{/discriminator}};
{{>modelOneOfInterfaces}}

export function {{classname}}FromJSON(json: any): {{classname}} {
return {{classname}}FromJSONTyped(json, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @type {{classname}}
* {{#lambda.indented_star_1}}{{{unescapedDescription}}}{{/lambda.indented_star_1}}
* @export
*/
export type {{classname}} = {{#discriminator}}{{#mappedModels}}{ {{discriminator.propertyName}}: '{{mappingName}}' } & {{modelName}}{{^-last}} | {{/-last}}{{/mappedModels}}{{/discriminator}}{{^discriminator}}{{#oneOf}}{{{.}}}{{^-last}} | {{/-last}}{{/oneOf}}{{/discriminator}};
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
{{#models}}
{{#model}}
{{^withoutRuntimeChecks}}
export * from './{{{ classFilename }}}';
{{/withoutRuntimeChecks}}{{#withoutRuntimeChecks}}
{{#isEnum}}
{{>modelEnumInterfaces}}
{{/isEnum}}
{{^isEnum}}
{{#oneOf}}
{{#-first}}
{{>modelOneOfInterfaces}}
{{/-first}}
{{/oneOf}}
{{^oneOf}}
{{>modelGenericInterfaces}}
{{/oneOf}}
{{/isEnum}}
{{/withoutRuntimeChecks}}
{{/model}}
{{/models}}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class TypeScriptFetchClientOptionsProvider implements OptionsProvider {
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
public static final String TYPESCRIPT_THREE_PLUS = "true";
public static final String WITHOUT_RUNTIME_CHECKS = "true";

@Override
public String getLanguage() {
Expand All @@ -64,6 +65,7 @@ public Map<String, String> createOptions() {
.put(TypeScriptFetchClientCodegen.USE_SINGLE_REQUEST_PARAMETER, Boolean.FALSE.toString())
.put(TypeScriptFetchClientCodegen.PREFIX_PARAMETER_INTERFACES, Boolean.FALSE.toString())
.put(TypeScriptFetchClientCodegen.TYPESCRIPT_THREE_PLUS, TYPESCRIPT_THREE_PLUS)
.put(TypeScriptFetchClientCodegen.WITHOUT_RUNTIME_CHECKS, WITHOUT_RUNTIME_CHECKS)
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
.put(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "true")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ protected void verifyOptions() {
verify(clientCodegen).setSupportsES6(TypeScriptFetchClientOptionsProvider.SUPPORTS_ES6_VALUE);
verify(clientCodegen).setPrependFormOrBodyParameters(Boolean.valueOf(TypeScriptFetchClientOptionsProvider.PREPEND_FORM_OR_BODY_PARAMETERS_VALUE));
verify(clientCodegen).setTypescriptThreePlus(Boolean.valueOf(TypeScriptFetchClientOptionsProvider.TYPESCRIPT_THREE_PLUS));
verify(clientCodegen).setWithoutRuntimeChecks(Boolean.valueOf(TypeScriptFetchClientOptionsProvider.WITHOUT_RUNTIME_CHECKS));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ export interface Order {
complete?: boolean;
}

/**
* @export
* @enum {string}
*/
export enum OrderStatusEnum {
Placed = 'placed',
Approved = 'approved',
Delivered = 'delivered'
}

export function OrderFromJSON(json: any): Order {
return OrderFromJSONTyped(json, false);
}
Expand Down Expand Up @@ -94,14 +104,4 @@ export function OrderToJSON(value?: Order | null): any {
};
}

/**
* @export
* @enum {string}
*/
export enum OrderStatusEnum {
Placed = 'placed',
Approved = 'approved',
Delivered = 'delivered'
}


Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ export interface Pet {
status?: PetStatusEnum;
}

/**
* @export
* @enum {string}
*/
export enum PetStatusEnum {
Available = 'available',
Pending = 'pending',
Sold = 'sold'
}

export function PetFromJSON(json: any): Pet {
return PetFromJSONTyped(json, false);
}
Expand Down Expand Up @@ -105,14 +115,4 @@ export function PetToJSON(value?: Pet | null): any {
};
}

/**
* @export
* @enum {string}
*/
export enum PetStatusEnum {
Available = 'available',
Pending = 'pending',
Sold = 'sold'
}


Loading

0 comments on commit 36aba26

Please sign in to comment.