Skip to content

Commit e2746e2

Browse files
author
Thibaud SOWA
committed
feat(typescript-angular): add options to override angular deps + refactor deps definition
add tsVersion, rxjsVersion, ngPackagrVersion and zonejsVersion options to override default config if new version of Angular is available but not yet implemented in openapi-generator refactor Angular dependencies definition in separate readable yaml config file fix #20204
1 parent 21d19fe commit e2746e2

File tree

7 files changed

+250
-118
lines changed

7 files changed

+250
-118
lines changed

modules/openapi-generator/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,11 @@
459459
<artifactId>lombok</artifactId>
460460
<version>${lombok.version}</version>
461461
</dependency>
462+
<dependency>
463+
<groupId>org.yaml</groupId>
464+
<artifactId>snakeyaml</artifactId>
465+
<version>${snakeyaml.version}</version>
466+
</dependency>
462467
</dependencies>
463468
<repositories>
464469
<repository>

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

Lines changed: 46 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import io.swagger.v3.oas.models.media.Schema;
2121
import lombok.AccessLevel;
22+
import lombok.Data;
2223
import lombok.Getter;
2324
import lombok.Setter;
2425
import org.openapitools.codegen.*;
@@ -31,6 +32,7 @@
3132
import org.openapitools.codegen.model.OperationsMap;
3233
import org.openapitools.codegen.utils.ModelUtils;
3334
import org.openapitools.codegen.utils.SemVer;
35+
import org.openapitools.codegen.utils.YamlConfigUtils;
3436
import org.slf4j.Logger;
3537
import org.slf4j.LoggerFactory;
3638

@@ -76,6 +78,10 @@ public static enum PROVIDED_IN_LEVEL {none, root, any, platform}
7678
public static final String STRING_ENUMS_DESC = "Generate string enums instead of objects for enum values.";
7779
public static final String QUERY_PARAM_OBJECT_FORMAT = "queryParamObjectFormat";
7880
public static final String USE_SQUARE_BRACKETS_IN_ARRAY_NAMES = "useSquareBracketsInArrayNames";
81+
public static final String TYPESCRIPT_VERSION = "typescriptVersion";
82+
public static final String RXJS_VERSION = "rxjsVersion";
83+
public static final String NGPACKAGR_VERSION = "ngPackagrVersion ";
84+
public static final String ZONEJS_VERSION = "zoneJsVersion";
7985

8086
protected String ngVersion = "19.0.0";
8187
@Getter @Setter
@@ -144,6 +150,10 @@ public TypeScriptAngularClientCodegen() {
144150
this.cliOptions.add(new CliOption(STRING_ENUMS, STRING_ENUMS_DESC).defaultValue(String.valueOf(this.stringEnums)));
145151
this.cliOptions.add(new CliOption(QUERY_PARAM_OBJECT_FORMAT, "The format for query param objects: 'dot', 'json', 'key'.").defaultValue(this.queryParamObjectFormat.name()));
146152
this.cliOptions.add(CliOption.newBoolean(USE_SQUARE_BRACKETS_IN_ARRAY_NAMES, "Setting this property to true will add brackets to array attribute names, e.g. my_values[].", false));
153+
this.cliOptions.add(new CliOption(TYPESCRIPT_VERSION, "The version of typescript compatible with Angular (see ngVersion option)."));
154+
this.cliOptions.add(new CliOption(RXJS_VERSION, "The version of RxJS compatible with Angular (see ngVersion option)."));
155+
this.cliOptions.add(new CliOption(NGPACKAGR_VERSION, "The version of ng-packagr compatible with Angular (see ngVersion option)."));
156+
this.cliOptions.add(new CliOption(ZONEJS_VERSION, "The version of zone.js compatible with Angular (see ngVersion option)."));
147157
}
148158

149159
@Override
@@ -286,135 +296,53 @@ public void processOpts() {
286296

287297
}
288298

299+
@Data
300+
static class AngularDependencies {
301+
String tsVersion;
302+
String rxjsVersion;
303+
String ngPackagrVersion;
304+
String zonejsVersion;
305+
String tsickleVersion;
306+
}
307+
289308
private void addNpmPackageGeneration(SemVer ngVersion) {
290309

291310
if (additionalProperties.containsKey(NPM_REPOSITORY)) {
292311
this.setNpmRepository(additionalProperties.get(NPM_REPOSITORY).toString());
293312
}
294313

295-
// Set the typescript version compatible to the Angular version
296-
// based on https://angular.dev/reference/versions
297-
if (ngVersion.atLeast("19.0.0")) {
298-
additionalProperties.put("tsVersion", ">=5.5.0 <5.7.0");
299-
} else if (ngVersion.atLeast("18.1.0")) {
300-
additionalProperties.put("tsVersion", ">=5.4.0 <5.6.0");
301-
} else if (ngVersion.atLeast("18.0.0")) {
302-
additionalProperties.put("tsVersion", ">=5.4.0 <5.5.0");
303-
} else if (ngVersion.atLeast("17.0.0")) {
304-
additionalProperties.put("tsVersion", ">=4.9.3 <5.3.0");
305-
} else if (ngVersion.atLeast("16.1.0")) {
306-
additionalProperties.put("tsVersion", ">=4.9.3 <5.2.0");
307-
} else if (ngVersion.atLeast("16.0.0")) {
308-
additionalProperties.put("tsVersion", ">=4.9.3 <5.1.0");
309-
} else if (ngVersion.atLeast("15.0.0")) {
310-
additionalProperties.put("tsVersion", ">=4.8.2 <4.10.0");
311-
} else if (ngVersion.atLeast("14.0.0")) {
312-
additionalProperties.put("tsVersion", ">=4.6.0 <=4.8.0");
313-
} else if (ngVersion.atLeast("13.0.0")) {
314-
additionalProperties.put("tsVersion", ">=4.4.2 <4.5.0");
315-
} else if (ngVersion.atLeast("12.0.0")) {
316-
additionalProperties.put("tsVersion", ">=4.3.0 <4.4.0");
317-
} else if (ngVersion.atLeast("11.0.0")) {
318-
additionalProperties.put("tsVersion", ">=4.0.0 <4.1.0");
319-
} else if (ngVersion.atLeast("10.0.0")) {
320-
additionalProperties.put("tsVersion", ">=3.9.2 <4.0.0");
321-
} else if (ngVersion.atLeast("9.0.0")) {
322-
additionalProperties.put("tsVersion", ">=3.6.0 <3.8.0");
323-
} else {
324-
throw new IllegalArgumentException("Invalid ngVersion. Only Angular v9+ is supported.");
325-
}
326-
327-
// Set the rxJS version compatible to the Angular version
328-
if (ngVersion.atLeast("19.0.0")) {
329-
additionalProperties.put("rxjsVersion", "7.4.0");
330-
} else if (ngVersion.atLeast("18.0.0")) {
331-
additionalProperties.put("rxjsVersion", "7.4.0");
332-
} else if (ngVersion.atLeast("17.0.0")) {
333-
additionalProperties.put("rxjsVersion", "7.4.0");
334-
} else if (ngVersion.atLeast("16.0.0")) {
335-
additionalProperties.put("rxjsVersion", "7.4.0");
336-
} else if (ngVersion.atLeast("15.0.0")) {
337-
additionalProperties.put("rxjsVersion", "7.5.5");
338-
} else if (ngVersion.atLeast("14.0.0")) {
339-
additionalProperties.put("rxjsVersion", "7.5.5");
340-
} else if (ngVersion.atLeast("13.0.0")) {
341-
additionalProperties.put("rxjsVersion", "7.4.0");
342-
} else if (ngVersion.atLeast("10.0.0")) {
343-
additionalProperties.put("rxjsVersion", "6.6.0");
344-
} else if (ngVersion.atLeast("9.0.0")) {
345-
additionalProperties.put("rxjsVersion", "6.5.3");
346-
}
314+
Map<String, AngularDependencies> angularDependenciesByVersion = YamlConfigUtils.loadAsMap("typescript-angular/angularDependenciesByVersion.yaml", AngularDependencies.class);
347315

348-
supportingFiles.add(new SupportingFile("ng-package.mustache", getIndexDirectory(), "ng-package.json"));
316+
AngularDependencies angularDependencies = angularDependenciesByVersion.entrySet().stream()
317+
// we filter only config version above or equal the current one
318+
.filter(versionMatrix -> ngVersion.atLeast(versionMatrix.getKey()))
319+
// get can the latest version configured that match the current one
320+
.max(Comparator.comparing(s -> new SemVer(s.getKey())))
321+
.map(Map.Entry::getValue)
322+
.orElseThrow(() -> new IllegalArgumentException("Invalid ngVersion. Only Angular v9+ is supported."));
349323

350-
// Specific ng-packagr configuration
351-
if (ngVersion.atLeast("19.0.0")) {
352-
additionalProperties.put("ngPackagrVersion", "19.0.0");
353-
} else if (ngVersion.atLeast("18.1.0")) {
354-
additionalProperties.put("ngPackagrVersion", "18.1.0");
355-
// tsTickle is not required and there is no available version compatible with
356-
// versions of TypeScript compatible with Angular 18.
357-
} else if (ngVersion.atLeast("18.0.0")) {
358-
additionalProperties.put("ngPackagrVersion", "18.0.0");
359-
// tsTickle is not required and there is no available version compatible with
360-
// versions of TypeScript compatible with Angular 18.
361-
} else if (ngVersion.atLeast("17.0.0")) {
362-
additionalProperties.put("ngPackagrVersion", "17.0.3");
363-
// tsTickle is not required and there is no available version compatible with
364-
// versions of TypeScript compatible with Angular 17.
365-
} else if (ngVersion.atLeast("16.0.0")) {
366-
additionalProperties.put("ngPackagrVersion", "16.0.0");
367-
// tsTickle is not required and there is no available version compatible with
368-
// versions of TypeScript compatible with Angular 16.
369-
} else if (ngVersion.atLeast("15.0.0")) {
370-
additionalProperties.put("ngPackagrVersion", "15.0.2");
371-
// tsTickle is not required and there is no available version compatible with
372-
// versions of TypeScript compatible with Angular 15.
373-
} else if (ngVersion.atLeast("14.0.0")) {
374-
additionalProperties.put("ngPackagrVersion", "14.0.2");
375-
additionalProperties.put("tsickleVersion", "0.46.3");
376-
} else if (ngVersion.atLeast("13.0.0")) {
377-
additionalProperties.put("ngPackagrVersion", "13.0.3");
378-
additionalProperties.put("tsickleVersion", "0.43.0");
379-
} else if (ngVersion.atLeast("12.0.0")) {
380-
additionalProperties.put("ngPackagrVersion", "12.2.1");
381-
additionalProperties.put("tsickleVersion", "0.43.0");
382-
} else if (ngVersion.atLeast("11.0.0")) {
383-
additionalProperties.put("ngPackagrVersion", "11.0.2");
384-
additionalProperties.put("tsickleVersion", "0.39.1");
385-
} else if (ngVersion.atLeast("10.0.0")) {
386-
additionalProperties.put("ngPackagrVersion", "10.0.3");
387-
additionalProperties.put("tsickleVersion", "0.39.1");
388-
} else if (ngVersion.atLeast("9.0.0")) {
389-
additionalProperties.put("ngPackagrVersion", "9.0.1");
390-
additionalProperties.put("tsickleVersion", "0.38.0");
391-
}
392-
393-
// set zone.js version
394-
// based on https://github.com/angular/angular/blob/main/packages/core/package.json
395-
if (ngVersion.atLeast("19.0.0")) {
396-
additionalProperties.put("zonejsVersion", "0.15.0");
397-
} else if (ngVersion.atLeast("18.0.0")) {
398-
additionalProperties.put("zonejsVersion", "0.14.7");
399-
} else if (ngVersion.atLeast("17.0.0")) {
400-
additionalProperties.put("zonejsVersion", "0.14.0");
401-
} else if (ngVersion.atLeast("16.0.0")) {
402-
additionalProperties.put("zonejsVersion", "0.13.0");
403-
} else if (ngVersion.atLeast("15.0.0")) {
404-
additionalProperties.put("zonejsVersion", "0.11.5");
405-
} else if (ngVersion.atLeast("14.0.0")) {
406-
additionalProperties.put("zonejsVersion", "0.11.5");
407-
} else if (ngVersion.atLeast("12.0.0")) {
408-
additionalProperties.put("zonejsVersion", "0.11.4");
409-
} else if (ngVersion.atLeast("11.0.0")) {
410-
additionalProperties.put("zonejsVersion", "0.11.3");
411-
} else if (ngVersion.atLeast("9.0.0")) {
412-
additionalProperties.put("zonejsVersion", "0.10.2");
413-
} else if (ngVersion.atLeast("8.0.0")) {
414-
additionalProperties.put("zonejsVersion", "0.9.1");
324+
additionalProperties.put("tsVersion", additionalProperties.containsKey(TYPESCRIPT_VERSION)
325+
? additionalProperties.containsKey(TYPESCRIPT_VERSION)
326+
: angularDependencies.getTsVersion());
327+
328+
additionalProperties.put("rxjsVersion", additionalProperties.containsKey(RXJS_VERSION)
329+
? additionalProperties.containsKey(RXJS_VERSION)
330+
: angularDependencies.getRxjsVersion());
331+
332+
additionalProperties.put("ngPackagrVersion", additionalProperties.containsKey(NGPACKAGR_VERSION)
333+
? additionalProperties.containsKey(NGPACKAGR_VERSION)
334+
: angularDependencies.getNgPackagrVersion());
335+
336+
additionalProperties.put("zonejsVersion", additionalProperties.containsKey(ZONEJS_VERSION)
337+
? additionalProperties.containsKey(ZONEJS_VERSION)
338+
: angularDependencies.getZonejsVersion());
339+
340+
if (angularDependencies.getTsickleVersion() != null) {
341+
additionalProperties.put("tsickleVersion", angularDependencies.getTsickleVersion());
415342
}
416343

417344
//Files for building our lib
345+
supportingFiles.add(new SupportingFile("ng-package.mustache", getIndexDirectory(), "ng-package.json"));
418346
supportingFiles.add(new SupportingFile("package.mustache", getIndexDirectory(), "package.json"));
419347
supportingFiles.add(new SupportingFile("tsconfig.mustache", getIndexDirectory(), "tsconfig.json"));
420348
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package org.openapitools.codegen.utils;
2+
3+
import org.yaml.snakeyaml.LoaderOptions;
4+
import org.yaml.snakeyaml.TypeDescription;
5+
import org.yaml.snakeyaml.Yaml;
6+
import org.yaml.snakeyaml.constructor.Constructor;
7+
import org.yaml.snakeyaml.introspector.BeanAccess;
8+
import org.yaml.snakeyaml.nodes.MappingNode;
9+
import org.yaml.snakeyaml.nodes.Node;
10+
import org.yaml.snakeyaml.nodes.Tag;
11+
12+
import java.io.InputStream;
13+
import java.util.Map;
14+
import java.util.stream.Collectors;
15+
16+
public class YamlConfigUtils {
17+
18+
/**
19+
* Load yaml config file as map
20+
*
21+
* @param configFile yaml config file to load
22+
* @param clazz class of object to map data
23+
* @param <T> type of config object to generate
24+
* @return config object generated
25+
*/
26+
public static <T> Map<String, T> loadAsMap(String configFile, Class<T> clazz) {
27+
LoaderOptions loaderOptions = new LoaderOptions();
28+
loaderOptions.setAllowDuplicateKeys(false);
29+
30+
Yaml yaml = new Yaml(new MapConstructor(loaderOptions, clazz));
31+
yaml.setBeanAccess(BeanAccess.FIELD);
32+
InputStream inputStream = YamlConfigUtils.class
33+
.getClassLoader()
34+
.getResourceAsStream(configFile);
35+
36+
return yaml.load(inputStream);
37+
}
38+
39+
private static class MapConstructor extends Constructor {
40+
private final TypeDescription itemType;
41+
42+
public <T> MapConstructor(LoaderOptions loaderOptions, Class<T> clazz) {
43+
super(loaderOptions);
44+
this.rootTag = new Tag("root");
45+
itemType = new TypeDescription(clazz);
46+
this.addTypeDescription(itemType);
47+
}
48+
49+
@Override
50+
protected Object constructObject(Node node) {
51+
if ("root".equals(node.getTag().getValue()) && node instanceof MappingNode) {
52+
MappingNode mNode = (MappingNode) node;
53+
return mNode.getValue().stream().collect(
54+
Collectors.toMap(
55+
t -> super.constructObject(t.getKeyNode()),
56+
t -> {
57+
Node child = t.getValueNode();
58+
child.setType(itemType.getType());
59+
return super.constructObject(child);
60+
}
61+
)
62+
);
63+
64+
} else {
65+
return super.constructObject(node);
66+
}
67+
}
68+
}
69+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# For future versions...
2+
# Get typescript and rxjs version here: https://angular.dev/reference/versions
3+
# Get zone.js version here: https://github.com/angular/angular/blob/main/packages/core/package.json
4+
19.0.0:
5+
tsVersion: '>=5.5.0 <5.7.0'
6+
rxjsVersion: 7.4.0
7+
ngPackagrVersion: 19.0.0
8+
zonejsVersion: 0.15.0
9+
18.1.0:
10+
tsVersion: '>=5.4.0 <5.6.0'
11+
rxjsVersion: 7.4.0
12+
ngPackagrVersion: 18.1.0
13+
zonejsVersion: 0.14.7
14+
18.0.0:
15+
tsVersion: '>=5.4.0 <5.5.0'
16+
rxjsVersion: 7.4.0
17+
ngPackagrVersion: 18.0.0
18+
zonejsVersion: 0.14.7
19+
17.0.0:
20+
tsVersion: '>=4.9.3 <5.3.0'
21+
rxjsVersion: 7.4.0
22+
ngPackagrVersion: 17.0.3
23+
zonejsVersion: 0.14.0
24+
16.1.0:
25+
tsVersion: '>=4.9.3 <5.2.0'
26+
rxjsVersion: 7.4.0
27+
ngPackagrVersion: 16.0.0
28+
zonejsVersion: 0.13.0
29+
16.0.0:
30+
tsVersion: '>=4.9.3 <5.1.0'
31+
rxjsVersion: 7.4.0
32+
ngPackagrVersion: 16.0.0
33+
zonejsVersion: 0.13.0
34+
15.0.0:
35+
tsVersion: '>=4.8.2 <4.10.0'
36+
rxjsVersion: 7.5.5
37+
ngPackagrVersion: 15.0.2
38+
zonejsVersion: 0.11.5
39+
14.0.0:
40+
tsVersion: '>=4.6.0 <=4.8.0'
41+
rxjsVersion: 7.5.5
42+
ngPackagrVersion: 14.0.2
43+
zonejsVersion: 0.11.5
44+
tsickleVersion: 0.46.3
45+
13.0.0:
46+
tsVersion: '>=4.4.2 <4.5.0'
47+
rxjsVersion: 7.4.0
48+
ngPackagrVersion: 13.0.3
49+
zonejsVersion: 0.11.4
50+
tsickleVersion: 0.43.0
51+
12.0.0:
52+
tsVersion: '>=4.3.0 <4.4.0'
53+
rxjsVersion: 6.6.0
54+
ngPackagrVersion: 12.2.1
55+
zonejsVersion: 0.11.4
56+
tsickleVersion: 0.43.0
57+
11.0.0:
58+
tsVersion: '>=4.0.0 <4.1.0'
59+
rxjsVersion: 6.6.0
60+
ngPackagrVersion: 11.0.2
61+
zonejsVersion: 0.11.3
62+
tsickleVersion: 0.39.1
63+
10.0.0:
64+
tsVersion: '>=3.9.2 <4.0.0'
65+
rxjsVersion: 6.6.0
66+
ngPackagrVersion: 10.0.3
67+
zonejsVersion: 0.10.2
68+
tsickleVersion: 0.39.1
69+
9.0.0:
70+
tsVersion: '>=3.6.0 <3.8.0'
71+
rxjsVersion: 6.5.3
72+
ngPackagrVersion: 9.0.1
73+
zonejsVersion: 0.10.2
74+
tsickleVersion: 0.39.1

0 commit comments

Comments
 (0)