Skip to content

Commit d39bf0f

Browse files
Joseph SemlakJoseph Semlak
authored andcommitted
feat(typescript-axios): add useErasableSyntax option for erasableSyntaxOnly compiler support
- Add useErasableSyntax option to TypeScriptAxiosClientCodegen (default: false) - Update baseApi.mustache to generate erasable syntax when enabled - Fix semicolons in configuration.mustache for consistency - Add comprehensive test coverage (4 new tests, all passing) - Regenerate all typescript-axios samples with semicolon fixes This change enables support for TypeScript's 'erasableSyntaxOnly' compiler option by generating code without parameter properties when useErasableSyntax is enabled. The feature is opt-in and fully backward compatible. Closes #[issue-number-if-applicable]
1 parent 59042aa commit d39bf0f

42 files changed

Lines changed: 3567 additions & 87 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
generatorName: typescript-axios
2+
outputDir: samples/client/petstore/typescript-axios/builds/with-erasable-syntax
3+
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/typescript-axios
5+
additionalProperties:
6+
stringEnums: true
7+
useErasableSyntax: true

docs/generators/typescript-axios.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
4242
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
4343
|stringEnums|Generate string enums instead of objects for enum values.| |false|
4444
|supportsES6|Generate code that conforms to ES6.| |false|
45+
|useErasableSyntax|Use erasable syntax for the generated code. This is a temporary feature and will be removed in the future.| |false|
4546
|useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |false|
4647
|useSquareBracketsInArrayNames|Setting this property to true will add brackets to array attribute names, e.g. my_values[].| |false|
4748
|withAWSV4Signature|whether to include AWS v4 signature support| |false|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAxiosClientCodegen.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ public class TypeScriptAxiosClientCodegen extends AbstractTypeScriptClientCodege
5454
public static final String DEFAULT_AXIOS_VERSION = "^1.6.1";
5555
public static final String WITH_AWSV4_SIGNATURE = "withAWSV4Signature";
5656

57+
public static final String USE_ERASABLE_SYNTAX = "useErasableSyntax";
58+
public static final String USE_ERASABLE_SYNTAX_DESC = "Use erasable syntax for the generated code (compatible with TypeScript's erasableSyntaxOnly compiler option). This is a temporary feature and will be removed in the future.";
59+
5760
@Getter @Setter
5861
protected String npmRepository = null;
5962
protected Boolean stringEnums = false;
@@ -97,6 +100,7 @@ public TypeScriptAxiosClientCodegen() {
97100
this.cliOptions.add(new CliOption(USE_SQUARE_BRACKETS_IN_ARRAY_NAMES, "Setting this property to true will add brackets to array attribute names, e.g. my_values[].", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
98101
this.cliOptions.add(new CliOption(AXIOS_VERSION, "Use this property to override the axios version in package.json").defaultValue(DEFAULT_AXIOS_VERSION));
99102
this.cliOptions.add(new CliOption(WITH_AWSV4_SIGNATURE, "whether to include AWS v4 signature support", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
103+
this.cliOptions.add(new CliOption(USE_ERASABLE_SYNTAX, USE_ERASABLE_SYNTAX_DESC, SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
100104
// Templates have no mapping between formatted property names and original base names so use only "original" and remove this option
101105
removeOption(CodegenConstants.MODEL_PROPERTY_NAMING);
102106
}
@@ -190,6 +194,11 @@ public void processOpts() {
190194
}
191195
additionalProperties.put(CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT, withAWSV4Signature);
192196

197+
if (additionalProperties.containsKey(USE_ERASABLE_SYNTAX)) {
198+
boolean useErasableSyntax = Boolean.parseBoolean(additionalProperties.get(USE_ERASABLE_SYNTAX).toString());
199+
additionalProperties.put("useErasableSyntax", useErasableSyntax);
200+
}
201+
193202
}
194203

195204
@Override

modules/openapi-generator/src/main/resources/typescript-axios/baseApi.mustache

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ export interface RequestArgs {
2525

2626
export class BaseAPI {
2727
protected configuration: Configuration | undefined;
28+
{{#useErasableSyntax}}
29+
protected basePath: string;
30+
protected axios: AxiosInstance;
31+
32+
constructor(configuration?: Configuration, basePath: string = BASE_PATH, axios: AxiosInstance = globalAxios) {
33+
this.configuration = configuration;
34+
this.basePath = configuration?.basePath ?? basePath;
35+
this.axios = axios;
36+
}
37+
}
38+
{{/useErasableSyntax}}
39+
{{^useErasableSyntax}}
2840

2941
constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) {
3042
if (configuration) {
@@ -33,12 +45,24 @@ export class BaseAPI {
3345
}
3446
}
3547
};
48+
{{/useErasableSyntax}}
3649

3750
export class RequiredError extends Error {
51+
{{#useErasableSyntax}}
52+
public field: string;
53+
54+
constructor(field: string, msg?: string) {
55+
super(msg);
56+
this.name = "RequiredError"
57+
this.field = field;
58+
}
59+
{{/useErasableSyntax}}
60+
{{^useErasableSyntax}}
3861
constructor(public field: string, msg?: string) {
3962
super(msg);
4063
this.name = "RequiredError"
4164
}
65+
{{/useErasableSyntax}}
4266
}
4367

4468
interface ServerMap {

modules/openapi-generator/src/main/resources/typescript-axios/configuration.mustache

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33

44
interface AWSv4Configuration {
55
options?: {
6-
region?: string
7-
service?: string
6+
region?: string;
7+
service?: string;
88
}
99
credentials?: {
10-
accessKeyId?: string
11-
secretAccessKey?: string,
12-
sessionToken?: string
10+
accessKeyId?: string;
11+
secretAccessKey?: string;
12+
sessionToken?: string;
1313
}
1414
}
1515

modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/axios/TypeScriptAxiosClientCodegenTest.java

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
package org.openapitools.codegen.typescript.axios;
22

3+
import org.openapitools.codegen.ClientOptInput;
34
import org.openapitools.codegen.CodegenConstants;
5+
import org.openapitools.codegen.DefaultGenerator;
46
import org.openapitools.codegen.SupportingFile;
7+
import org.openapitools.codegen.TestUtils;
8+
import org.openapitools.codegen.config.CodegenConfigurator;
59
import org.openapitools.codegen.languages.TypeScriptAxiosClientCodegen;
610
import org.openapitools.codegen.typescript.TypeScriptGroups;
711
import org.testng.annotations.Test;
812

13+
import java.io.File;
14+
import java.io.IOException;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
import java.nio.file.Paths;
18+
import java.util.List;
19+
920
import static org.assertj.core.api.Assertions.assertThat;
1021
import static org.testng.Assert.assertEquals;
22+
import static org.testng.Assert.assertFalse;
23+
import static org.testng.Assert.assertTrue;
1124

1225
@Test(groups = {TypeScriptGroups.TYPESCRIPT, TypeScriptGroups.TYPESCRIPT_AXIOS})
1326
public class TypeScriptAxiosClientCodegenTest {
@@ -130,4 +143,85 @@ public void testAppliesCustomAxiosVersion() {
130143

131144
assertEquals(codegen.additionalProperties().get("axiosVersion"), "^1.2.3");
132145
}
146+
147+
@Test
148+
public void testDefaultUseErasableSyntaxIsFalse() {
149+
TypeScriptAxiosClientCodegen codegen = new TypeScriptAxiosClientCodegen();
150+
151+
codegen.processOpts();
152+
153+
// useErasableSyntax should not be set when not specified (defaults to false behavior)
154+
assertFalse(codegen.additionalProperties().containsKey("useErasableSyntax"));
155+
}
156+
157+
@Test
158+
public void testUseErasableSyntaxSetToTrue() {
159+
TypeScriptAxiosClientCodegen codegen = new TypeScriptAxiosClientCodegen();
160+
codegen.additionalProperties().put("useErasableSyntax", true);
161+
162+
codegen.processOpts();
163+
164+
assertEquals(codegen.additionalProperties().get("useErasableSyntax"), true);
165+
}
166+
167+
@Test
168+
public void testUseErasableSyntaxSetToFalse() {
169+
TypeScriptAxiosClientCodegen codegen = new TypeScriptAxiosClientCodegen();
170+
codegen.additionalProperties().put("useErasableSyntax", false);
171+
172+
codegen.processOpts();
173+
174+
assertEquals(codegen.additionalProperties().get("useErasableSyntax"), false);
175+
}
176+
177+
@Test(description = "Verify useErasableSyntax config parameter generates erasable code")
178+
public void testUseErasableSyntaxGeneratesCorrectCode() throws IOException {
179+
boolean[] options = {true, false};
180+
for (boolean useErasableSyntax : options) {
181+
final File output = Files.createTempDirectory("typescript-axios-erasable-").toFile();
182+
output.deleteOnExit();
183+
184+
final CodegenConfigurator configurator = new CodegenConfigurator()
185+
.setGeneratorName("typescript-axios")
186+
.setInputSpec("src/test/resources/3_0/petstore.yaml")
187+
.addAdditionalProperty("useErasableSyntax", useErasableSyntax)
188+
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
189+
190+
final ClientOptInput clientOptInput = configurator.toClientOptInput();
191+
final DefaultGenerator generator = new DefaultGenerator();
192+
final List<File> files = generator.opts(clientOptInput).generate();
193+
files.forEach(File::deleteOnExit);
194+
195+
Path basePath = Paths.get(output + "/base.ts");
196+
TestUtils.assertFileExists(basePath);
197+
198+
if (useErasableSyntax) {
199+
// With erasable syntax: explicit property declarations
200+
TestUtils.assertFileContains(basePath, "protected basePath: string;");
201+
TestUtils.assertFileContains(basePath, "protected axios: AxiosInstance;");
202+
// Constructor parameters should NOT have access modifiers
203+
TestUtils.assertFileContains(basePath, "constructor(configuration?: Configuration, basePath: string = BASE_PATH, axios: AxiosInstance = globalAxios)");
204+
// Explicit assignments in constructor
205+
TestUtils.assertFileContains(basePath, "this.basePath = configuration?.basePath ?? basePath;");
206+
TestUtils.assertFileContains(basePath, "this.axios = axios;");
207+
// Class should close with } not };
208+
TestUtils.assertFileNotContains(basePath, "};\n\nexport class RequiredError");
209+
210+
// RequiredError should have explicit field declaration
211+
TestUtils.assertFileContains(basePath, "public field: string;");
212+
TestUtils.assertFileContains(basePath, "this.field = field;");
213+
} else {
214+
// Without erasable syntax: parameter properties
215+
TestUtils.assertFileContains(basePath, "constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios)");
216+
// Should have if (configuration) check
217+
TestUtils.assertFileContains(basePath, "if (configuration)");
218+
// Class should close with };
219+
TestUtils.assertFileContains(basePath, "};\n\nexport class RequiredError");
220+
221+
// RequiredError should use parameter property
222+
TestUtils.assertFileContains(basePath, "constructor(public field: string, msg?: string)");
223+
TestUtils.assertFileNotContains(basePath, "this.field = field;");
224+
}
225+
}
226+
}
133227
}

samples/client/echo_api/typescript-axios/build/configuration.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313

1414
interface AWSv4Configuration {
1515
options?: {
16-
region?: string
17-
service?: string
16+
region?: string;
17+
service?: string;
1818
}
1919
credentials?: {
20-
accessKeyId?: string
21-
secretAccessKey?: string,
22-
sessionToken?: string
20+
accessKeyId?: string;
21+
secretAccessKey?: string;
22+
sessionToken?: string;
2323
}
2424
}
2525

samples/client/others/typescript-axios/with-separate-models-and-api-inheritance/configuration.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313

1414
interface AWSv4Configuration {
1515
options?: {
16-
region?: string
17-
service?: string
16+
region?: string;
17+
service?: string;
1818
}
1919
credentials?: {
20-
accessKeyId?: string
21-
secretAccessKey?: string,
22-
sessionToken?: string
20+
accessKeyId?: string;
21+
secretAccessKey?: string;
22+
sessionToken?: string;
2323
}
2424
}
2525

samples/client/petstore/typescript-axios/builds/composed-schemas/configuration.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313

1414
interface AWSv4Configuration {
1515
options?: {
16-
region?: string
17-
service?: string
16+
region?: string;
17+
service?: string;
1818
}
1919
credentials?: {
20-
accessKeyId?: string
21-
secretAccessKey?: string,
22-
sessionToken?: string
20+
accessKeyId?: string;
21+
secretAccessKey?: string;
22+
sessionToken?: string;
2323
}
2424
}
2525

samples/client/petstore/typescript-axios/builds/default/configuration.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313

1414
interface AWSv4Configuration {
1515
options?: {
16-
region?: string
17-
service?: string
16+
region?: string;
17+
service?: string;
1818
}
1919
credentials?: {
20-
accessKeyId?: string
21-
secretAccessKey?: string,
22-
sessionToken?: string
20+
accessKeyId?: string;
21+
secretAccessKey?: string;
22+
sessionToken?: string;
2323
}
2424
}
2525

0 commit comments

Comments
 (0)