Skip to content

Commit 64ab13a

Browse files
authored
feat(typescript-angular): add Angular 20 support (#21563)
* feat(typescript-angular): add Angular 20 support * chore: remove unused .openapi-generator-ignore file
1 parent f9098d5 commit 64ab13a

File tree

32 files changed

+2401
-4
lines changed

32 files changed

+2401
-4
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
generatorName: typescript-angular
2+
outputDir: samples/client/petstore/typescript-angular-v20/builds/default
3+
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/typescript-angular
5+
additionalProperties:
6+
ngVersion: 20.0.0
7+
npmName: sample-angular-20-0-0
8+
supportsES6: true

docs/generators/typescript-angular.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ title: Documentation for the typescript-angular Generator
1111
| generator type | CLIENT | |
1212
| generator language | Typescript | |
1313
| generator default templating engine | mustache | |
14-
| helpTxt | Generates a TypeScript Angular (9.x - 19.x) client library. | |
14+
| helpTxt | Generates a TypeScript Angular (9.x - 20.x) client library. | |
1515

1616
## CONFIG OPTIONS
1717
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
@@ -34,7 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
3434
|modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name. Only change it if you provide your own run-time code for (de-)serialization of models| |original|
3535
|modelSuffix|The suffix of the generated model.| |null|
3636
|ngPackagrVersion|The version of ng-packagr compatible with Angular (see ngVersion option).| |null|
37-
|ngVersion|The version of Angular. (At least 9.0.0)| |19.0.0|
37+
|ngVersion|The version of Angular. (At least 9.0.0)| |20.0.0|
3838
|npmName|The name under which you want to publish generated npm package. Required to generate a full package| |null|
3939
|npmRepository|Use this property to set an url your private npmRepo in the package.json| |null|
4040
|npmVersion|The version of your npm package. If not provided, using the version from the OpenAPI specification file.| |1.0.0|

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public static enum PROVIDED_IN_LEVEL {none, root, any, platform}
8484
public static final String NGPACKAGR_VERSION = "ngPackagrVersion";
8585
public static final String ZONEJS_VERSION = "zonejsVersion";
8686

87-
protected String ngVersion = "19.0.0";
87+
protected String ngVersion = "20.0.0";
8888
@Getter @Setter
8989
protected String npmRepository = null;
9090
@Setter(AccessLevel.PRIVATE) private boolean useSingleRequestParameter = false;
@@ -170,7 +170,7 @@ public String getName() {
170170

171171
@Override
172172
public String getHelp() {
173-
return "Generates a TypeScript Angular (9.x - 19.x) client library.";
173+
return "Generates a TypeScript Angular (9.x - 20.x) client library.";
174174
}
175175

176176
@Override

modules/openapi-generator/src/main/resources/typescript-angular/angularDependenciesByVersion.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# For future versions...
22
# Get typescript and rxjs version here: https://angular.dev/reference/versions
33
# Get zone.js version here: https://github.com/angular/angular/blob/main/packages/core/package.json
4+
20.0.0:
5+
tsVersion: '>=5.8.0 <5.9.0'
6+
rxjsVersion: 7.4.0
7+
ngPackagrVersion: 20.0.0
8+
zonejsVersion: 0.15.0
49
19.0.0:
510
tsVersion: '>=5.5.0 <5.7.0'
611
rxjsVersion: 7.4.0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
wwwroot/*.js
2+
node_modules
3+
typings
4+
dist
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
# The patterns follow closely to .gitignore or .dockerignore.
6+
7+
# As an example, the C# client generator defines ApiClient.cs.
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9+
#ApiClient.cs
10+
11+
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
12+
#foo/*/qux
13+
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14+
15+
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16+
#foo/**/qux
17+
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18+
19+
# You can also negate patterns with an exclamation (!).
20+
# For example, you can ignore all files in a docs folder with the file extension .md:
21+
#docs/*.md
22+
# Then explicitly reverse the ignore rule for a single file:
23+
#!docs/README.md
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
.gitignore
2+
README.md
3+
api.base.service.ts
4+
api.module.ts
5+
api/api.ts
6+
api/pet.service.ts
7+
api/store.service.ts
8+
api/user.service.ts
9+
configuration.ts
10+
encoder.ts
11+
git_push.sh
12+
index.ts
13+
model/apiResponse.ts
14+
model/category.ts
15+
model/models.ts
16+
model/order.ts
17+
model/pet.ts
18+
model/tag.ts
19+
model/user.ts
20+
ng-package.json
21+
package.json
22+
param.ts
23+
provide-api.ts
24+
tsconfig.json
25+
variables.ts
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7.15.0-SNAPSHOT
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# sample-angular-20-0-0@1.0.0
2+
3+
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
4+
5+
The version of the OpenAPI document: 1.0.0
6+
7+
## Building
8+
9+
To install the required dependencies and to build the typescript sources run:
10+
11+
```console
12+
npm install
13+
npm run build
14+
```
15+
16+
## Publishing
17+
18+
First build the package then run `npm publish dist` (don't forget to specify the `dist` folder!)
19+
20+
## Consuming
21+
22+
Navigate to the folder of your consuming project and run one of next commands.
23+
24+
_published:_
25+
26+
```console
27+
npm install sample-angular-20-0-0@1.0.0 --save
28+
```
29+
30+
_without publishing (not recommended):_
31+
32+
```console
33+
npm install PATH_TO_GENERATED_PACKAGE/dist.tgz --save
34+
```
35+
36+
_It's important to take the tgz file, otherwise you'll get trouble with links on windows_
37+
38+
_using `npm link`:_
39+
40+
In PATH_TO_GENERATED_PACKAGE/dist:
41+
42+
```console
43+
npm link
44+
```
45+
46+
In your project:
47+
48+
```console
49+
npm link sample-angular-20-0-0
50+
```
51+
52+
__Note for Windows users:__ The Angular CLI has troubles to use linked npm packages.
53+
Please refer to this issue <https://github.com/angular/angular-cli/issues/8284> for a solution / workaround.
54+
Published packages are not effected by this issue.
55+
56+
### General usage
57+
58+
In your Angular project:
59+
60+
```typescript
61+
62+
import { ApplicationConfig } from '@angular/core';
63+
import { provideHttpClient } from '@angular/common/http';
64+
import { provideApi } from 'sample-angular-20-0-0';
65+
66+
export const appConfig: ApplicationConfig = {
67+
providers: [
68+
// ...
69+
provideHttpClient(),
70+
provideApi()
71+
],
72+
};
73+
```
74+
75+
**NOTE**
76+
If you're still using `AppModule` and haven't [migrated](https://angular.dev/reference/migrations/standalone) yet, you can still import an Angular module:
77+
```typescript
78+
import { ApiModule } from 'sample-angular-20-0-0';
79+
```
80+
81+
If different from the generated base path, during app bootstrap, you can provide the base path to your service.
82+
83+
```typescript
84+
import { ApplicationConfig } from '@angular/core';
85+
import { provideHttpClient } from '@angular/common/http';
86+
import { provideApi } from 'sample-angular-20-0-0';
87+
88+
export const appConfig: ApplicationConfig = {
89+
providers: [
90+
// ...
91+
provideHttpClient(),
92+
provideApi('http://localhost:9999')
93+
],
94+
};
95+
```
96+
97+
```typescript
98+
// with a custom configuration
99+
import { ApplicationConfig } from '@angular/core';
100+
import { provideHttpClient } from '@angular/common/http';
101+
import { provideApi } from 'sample-angular-20-0-0';
102+
103+
export const appConfig: ApplicationConfig = {
104+
providers: [
105+
// ...
106+
provideHttpClient(),
107+
provideApi({
108+
withCredentials: true,
109+
username: 'user',
110+
password: 'password'
111+
})
112+
],
113+
};
114+
```
115+
116+
```typescript
117+
// with factory building a custom configuration
118+
import { ApplicationConfig } from '@angular/core';
119+
import { provideHttpClient } from '@angular/common/http';
120+
import { provideApi, Configuration } from 'sample-angular-20-0-0';
121+
122+
export const appConfig: ApplicationConfig = {
123+
providers: [
124+
// ...
125+
provideHttpClient(),
126+
{
127+
provide: Configuration,
128+
useFactory: (authService: AuthService) => new Configuration({
129+
basePath: 'http://localhost:9999',
130+
withCredentials: true,
131+
username: authService.getUsername(),
132+
password: authService.getPassword(),
133+
}),
134+
deps: [AuthService],
135+
multi: false
136+
}
137+
],
138+
};
139+
```
140+
141+
### Using multiple OpenAPI files / APIs
142+
143+
In order to use multiple APIs generated from different OpenAPI files,
144+
you can create an alias name when importing the modules
145+
in order to avoid naming conflicts:
146+
147+
```typescript
148+
import { provideApi as provideUserApi } from 'my-user-api-path';
149+
import { provideApi as provideAdminApi } from 'my-admin-api-path';
150+
import { HttpClientModule } from '@angular/common/http';
151+
import { environment } from '../environments/environment';
152+
153+
export const appConfig: ApplicationConfig = {
154+
providers: [
155+
// ...
156+
provideHttpClient(),
157+
provideUserApi(environment.basePath),
158+
provideAdminApi(environment.basePath),
159+
],
160+
};
161+
```
162+
163+
### Customizing path parameter encoding
164+
165+
Without further customization, only [path-parameters][parameter-locations-url] of [style][style-values-url] 'simple'
166+
and Dates for format 'date-time' are encoded correctly.
167+
168+
Other styles (e.g. "matrix") are not that easy to encode
169+
and thus are best delegated to other libraries (e.g.: [@honoluluhenk/http-param-expander]).
170+
171+
To implement your own parameter encoding (or call another library),
172+
pass an arrow-function or method-reference to the `encodeParam` property of the Configuration-object
173+
(see [General Usage](#general-usage) above).
174+
175+
Example value for use in your Configuration-Provider:
176+
177+
```typescript
178+
new Configuration({
179+
encodeParam: (param: Param) => myFancyParamEncoder(param),
180+
})
181+
```
182+
183+
[parameter-locations-url]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-locations
184+
[style-values-url]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#style-values
185+
[@honoluluhenk/http-param-expander]: https://www.npmjs.com/package/@honoluluhenk/http-param-expander
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* OpenAPI Petstore
3+
*
4+
*
5+
*
6+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
7+
* https://openapi-generator.tech
8+
* Do not edit the class manually.
9+
*/
10+
import { HttpHeaders, HttpParams, HttpParameterCodec } from '@angular/common/http';
11+
import { CustomHttpParameterCodec } from './encoder';
12+
import { Configuration } from './configuration';
13+
14+
export class BaseService {
15+
protected basePath = 'http://petstore.swagger.io/v2';
16+
public defaultHeaders = new HttpHeaders();
17+
public configuration: Configuration;
18+
public encoder: HttpParameterCodec;
19+
20+
constructor(basePath?: string|string[], configuration?: Configuration) {
21+
this.configuration = configuration || new Configuration();
22+
if (typeof this.configuration.basePath !== 'string') {
23+
const firstBasePath = Array.isArray(basePath) ? basePath[0] : undefined;
24+
if (firstBasePath != undefined) {
25+
basePath = firstBasePath;
26+
}
27+
28+
if (typeof basePath !== 'string') {
29+
basePath = this.basePath;
30+
}
31+
this.configuration.basePath = basePath;
32+
}
33+
this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
34+
}
35+
36+
protected canConsumeForm(consumes: string[]): boolean {
37+
return consumes.indexOf('multipart/form-data') !== -1;
38+
}
39+
40+
protected addToHttpParams(httpParams: HttpParams, value: any, key?: string, isDeep: boolean = false): HttpParams {
41+
// If the value is an object (but not a Date), recursively add its keys.
42+
if (typeof value === 'object' && !(value instanceof Date)) {
43+
return this.addToHttpParamsRecursive(httpParams, value, isDeep ? key : undefined, isDeep);
44+
}
45+
return this.addToHttpParamsRecursive(httpParams, value, key);
46+
}
47+
48+
protected addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string, isDeep: boolean = false): HttpParams {
49+
if (value === null || value === undefined) {
50+
return httpParams;
51+
}
52+
if (typeof value === 'object') {
53+
// If JSON format is preferred, key must be provided.
54+
if (key != null) {
55+
return isDeep
56+
? Object.keys(value as Record<string, any>).reduce(
57+
(hp, k) => hp.append(`${key}[${k}]`, value[k]),
58+
httpParams,
59+
)
60+
: httpParams.append(key, JSON.stringify(value));
61+
}
62+
// Otherwise, if it's an array, add each element.
63+
if (Array.isArray(value)) {
64+
value.forEach(elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key));
65+
} else if (value instanceof Date) {
66+
if (key != null) {
67+
httpParams = httpParams.append(key, value.toISOString());
68+
} else {
69+
throw Error("key may not be null if value is Date");
70+
}
71+
} else {
72+
Object.keys(value).forEach(k => {
73+
const paramKey = key ? `${key}.${k}` : k;
74+
httpParams = this.addToHttpParamsRecursive(httpParams, value[k], paramKey);
75+
});
76+
}
77+
return httpParams;
78+
} else if (key != null) {
79+
return httpParams.append(key, value);
80+
}
81+
throw Error("key may not be null if value is not object or array");
82+
}
83+
}

0 commit comments

Comments
 (0)