Skip to content

Commit 9ca4bac

Browse files
typescript-inversify: improve check for required parameters, support multiple media types (#3849)
* [typescript-inversify] Allow falsy parameters A required parameter to an api method must not be `null` or `undefined`. It can be any other falsy value, e.g. `""`, `0` or `false` though. This change makes sure an error is only thrown in the former case and not in the latter. * [typescript-inversify] Handle multiple media types The Accept and Content-Type HTTP headers can contain a list of media types. Previously all but the first media type in the api definition were ignored. Now the headers are properly generated. * [typescript-inversify] Fix http client interface The api service methods allow the `body` parameter to be optional. The parameter is then passed to an `IHttpClient`. So it needs to be optional there as well. Also fixed the sample implementation `HttpClient`. Fixes #3618. * [typescript-inversify] Regenerate Petstore sample * [typescript-inversify] Use more explicit null check This does not change the semantic of the generated code, but makes it more explicit. Co-Authored-By: Esteban Gehring <[email protected]>
1 parent f2fe4fc commit 9ca4bac

File tree

10 files changed

+53
-47
lines changed

10 files changed

+53
-47
lines changed

modules/openapi-generator/src/main/resources/typescript-inversify/HttpClient.mustache

+8-5
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ class HttpClient implements IHttpClient {
1919
return this.performNetworkCall(url, "GET", undefined, headers);
2020
}
2121

22-
post(url: string, body: {}|FormData, headers?: Headers): Observable<HttpResponse> {
22+
post(url: string, body?: {}|FormData, headers?: Headers): Observable<HttpResponse> {
2323
return this.performNetworkCall(url, "POST", this.getJsonBody(body), this.addJsonHeaders(headers));
2424
}
2525

26-
put(url: string, body: {}, headers?: Headers): Observable<HttpResponse> {
26+
put(url: string, body?: {}, headers?: Headers): Observable<HttpResponse> {
2727
return this.performNetworkCall(url, "PUT", this.getJsonBody(body), this.addJsonHeaders(headers));
2828
}
2929

30-
patch(url: string, body: {}, headers?: Headers): Observable<HttpResponse> {
30+
patch(url: string, body?: {}, headers?: Headers): Observable<HttpResponse> {
3131
return this.performNetworkCall(url, "PATCH", this.getJsonBody(body), this.addJsonHeaders(headers));
3232
}
3333

@@ -36,8 +36,11 @@ class HttpClient implements IHttpClient {
3636
return this.performNetworkCall(url, "DELETE", undefined, headers);
3737
}
3838

39-
private getJsonBody(body: {}|FormData) {
40-
return !(body instanceof FormData) ? JSON.stringify(body) : body;
39+
private getJsonBody(body?: {}|FormData) {
40+
if (body === undefined || body instanceof FormData) {
41+
return body;
42+
}
43+
return JSON.stringify(body);
4144
}
4245

4346
private addJsonHeaders(headers?: Headers) {

modules/openapi-generator/src/main/resources/typescript-inversify/IHttpClient.mustache

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import { Headers } from "./Headers";
99

1010
interface IHttpClient {
1111
get(url:string, headers?: Headers):Observable<HttpResponse>
12-
post(url:string, body:{}|FormData, headers?: Headers):Observable<HttpResponse>
13-
put(url:string, body:{}, headers?: Headers):Observable<HttpResponse>
14-
patch(url:string, body:{}, headers?: Headers):Observable<HttpResponse>
12+
post(url:string, body?:{}|FormData, headers?: Headers):Observable<HttpResponse>
13+
put(url:string, body?:{}, headers?: Headers):Observable<HttpResponse>
14+
patch(url:string, body?:{}, headers?: Headers):Observable<HttpResponse>
1515
delete(url:string, headers?: Headers):Observable<HttpResponse>
1616
}
1717

modules/openapi-generator/src/main/resources/typescript-inversify/api.service.mustache

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export class {{classname}} {
6060
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}observe: any = 'body', headers: Headers = {}): {{#usePromise}}Promise{{/usePromise}}{{^usePromise}}Observable{{/usePromise}}<any> {
6161
{{#allParams}}
6262
{{#required}}
63-
if (!{{paramName}}){
63+
if ({{paramName}} === null || {{paramName}} === undefined){
6464
throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.');
6565
}
6666

@@ -139,7 +139,7 @@ export class {{classname}} {
139139
headers['Accept'] = 'application/json';
140140
{{/produces}}
141141
{{#produces.0}}
142-
headers['Accept'] = '{{{mediaType}}}';
142+
headers['Accept'] = '{{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}';
143143
{{/produces.0}}
144144
{{#bodyParam}}
145145
{{^consumes}}

samples/client/petstore/typescript-inversify/HttpClient.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ class HttpClient implements IHttpClient {
1414
return this.performNetworkCall(url, "GET", undefined, headers);
1515
}
1616

17-
post(url: string, body: {}|FormData, headers?: Headers): Observable<HttpResponse> {
17+
post(url: string, body?: {}|FormData, headers?: Headers): Observable<HttpResponse> {
1818
return this.performNetworkCall(url, "POST", this.getJsonBody(body), this.addJsonHeaders(headers));
1919
}
2020

21-
put(url: string, body: {}, headers?: Headers): Observable<HttpResponse> {
21+
put(url: string, body?: {}, headers?: Headers): Observable<HttpResponse> {
2222
return this.performNetworkCall(url, "PUT", this.getJsonBody(body), this.addJsonHeaders(headers));
2323
}
2424

25-
patch(url: string, body: {}, headers?: Headers): Observable<HttpResponse> {
25+
patch(url: string, body?: {}, headers?: Headers): Observable<HttpResponse> {
2626
return this.performNetworkCall(url, "PATCH", this.getJsonBody(body), this.addJsonHeaders(headers));
2727
}
2828

@@ -31,8 +31,11 @@ class HttpClient implements IHttpClient {
3131
return this.performNetworkCall(url, "DELETE", undefined, headers);
3232
}
3333

34-
private getJsonBody(body: {}|FormData) {
35-
return !(body instanceof FormData) ? JSON.stringify(body) : body;
34+
private getJsonBody(body?: {}|FormData) {
35+
if (body === undefined || body instanceof FormData) {
36+
return body;
37+
}
38+
return JSON.stringify(body);
3639
}
3740

3841
private addJsonHeaders(headers?: Headers) {

samples/client/petstore/typescript-inversify/IHttpClient.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { Headers } from "./Headers";
44

55
interface IHttpClient {
66
get(url:string, headers?: Headers):Observable<HttpResponse>
7-
post(url:string, body:{}|FormData, headers?: Headers):Observable<HttpResponse>
8-
put(url:string, body:{}, headers?: Headers):Observable<HttpResponse>
9-
patch(url:string, body:{}, headers?: Headers):Observable<HttpResponse>
7+
post(url:string, body?:{}|FormData, headers?: Headers):Observable<HttpResponse>
8+
put(url:string, body?:{}, headers?: Headers):Observable<HttpResponse>
9+
patch(url:string, body?:{}, headers?: Headers):Observable<HttpResponse>
1010
delete(url:string, headers?: Headers):Observable<HttpResponse>
1111
}
1212

samples/client/petstore/typescript-inversify/api/pet.service.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class PetService {
4646
public addPet(body: Pet, observe?: 'body', headers?: Headers): Observable<any>;
4747
public addPet(body: Pet, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
4848
public addPet(body: Pet, observe: any = 'body', headers: Headers = {}): Observable<any> {
49-
if (!body){
49+
if (body === null || body === undefined){
5050
throw new Error('Required parameter body was null or undefined when calling addPet.');
5151
}
5252

@@ -80,7 +80,7 @@ export class PetService {
8080
public deletePet(petId: number, apiKey?: string, observe?: 'body', headers?: Headers): Observable<any>;
8181
public deletePet(petId: number, apiKey?: string, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
8282
public deletePet(petId: number, apiKey?: string, observe: any = 'body', headers: Headers = {}): Observable<any> {
83-
if (!petId){
83+
if (petId === null || petId === undefined){
8484
throw new Error('Required parameter petId was null or undefined when calling deletePet.');
8585
}
8686

@@ -116,7 +116,7 @@ export class PetService {
116116
public findPetsByStatus(status: Array<'available' | 'pending' | 'sold'>, observe?: 'body', headers?: Headers): Observable<Array<Pet>>;
117117
public findPetsByStatus(status: Array<'available' | 'pending' | 'sold'>, observe?: 'response', headers?: Headers): Observable<HttpResponse<Array<Pet>>>;
118118
public findPetsByStatus(status: Array<'available' | 'pending' | 'sold'>, observe: any = 'body', headers: Headers = {}): Observable<any> {
119-
if (!status){
119+
if (status === null || status === undefined){
120120
throw new Error('Required parameter status was null or undefined when calling findPetsByStatus.');
121121
}
122122

@@ -132,7 +132,7 @@ export class PetService {
132132
: this.APIConfiguration.accessToken;
133133
headers['Authorization'] = 'Bearer ' + accessToken;
134134
}
135-
headers['Accept'] = 'application/xml';
135+
headers['Accept'] = 'application/xml, application/json';
136136

137137
const response: Observable<HttpResponse<Array<Pet>>> = this.httpClient.get(`${this.basePath}/pet/findByStatus?${queryParameters.join('&')}`, headers);
138138
if (observe == 'body') {
@@ -153,7 +153,7 @@ export class PetService {
153153
public findPetsByTags(tags: Array<string>, observe?: 'body', headers?: Headers): Observable<Array<Pet>>;
154154
public findPetsByTags(tags: Array<string>, observe?: 'response', headers?: Headers): Observable<HttpResponse<Array<Pet>>>;
155155
public findPetsByTags(tags: Array<string>, observe: any = 'body', headers: Headers = {}): Observable<any> {
156-
if (!tags){
156+
if (tags === null || tags === undefined){
157157
throw new Error('Required parameter tags was null or undefined when calling findPetsByTags.');
158158
}
159159

@@ -169,7 +169,7 @@ export class PetService {
169169
: this.APIConfiguration.accessToken;
170170
headers['Authorization'] = 'Bearer ' + accessToken;
171171
}
172-
headers['Accept'] = 'application/xml';
172+
headers['Accept'] = 'application/xml, application/json';
173173

174174
const response: Observable<HttpResponse<Array<Pet>>> = this.httpClient.get(`${this.basePath}/pet/findByTags?${queryParameters.join('&')}`, headers);
175175
if (observe == 'body') {
@@ -190,15 +190,15 @@ export class PetService {
190190
public getPetById(petId: number, observe?: 'body', headers?: Headers): Observable<Pet>;
191191
public getPetById(petId: number, observe?: 'response', headers?: Headers): Observable<HttpResponse<Pet>>;
192192
public getPetById(petId: number, observe: any = 'body', headers: Headers = {}): Observable<any> {
193-
if (!petId){
193+
if (petId === null || petId === undefined){
194194
throw new Error('Required parameter petId was null or undefined when calling getPetById.');
195195
}
196196

197197
// authentication (api_key) required
198198
if (this.APIConfiguration.apiKeys && this.APIConfiguration.apiKeys["api_key"]) {
199199
headers['api_key'] = this.APIConfiguration.apiKeys["api_key"];
200200
}
201-
headers['Accept'] = 'application/xml';
201+
headers['Accept'] = 'application/xml, application/json';
202202

203203
const response: Observable<HttpResponse<Pet>> = this.httpClient.get(`${this.basePath}/pet/${encodeURIComponent(String(petId))}`, headers);
204204
if (observe == 'body') {
@@ -219,7 +219,7 @@ export class PetService {
219219
public updatePet(body: Pet, observe?: 'body', headers?: Headers): Observable<any>;
220220
public updatePet(body: Pet, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
221221
public updatePet(body: Pet, observe: any = 'body', headers: Headers = {}): Observable<any> {
222-
if (!body){
222+
if (body === null || body === undefined){
223223
throw new Error('Required parameter body was null or undefined when calling updatePet.');
224224
}
225225

@@ -254,7 +254,7 @@ export class PetService {
254254
public updatePetWithForm(petId: number, name?: string, status?: string, observe?: 'body', headers?: Headers): Observable<any>;
255255
public updatePetWithForm(petId: number, name?: string, status?: string, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
256256
public updatePetWithForm(petId: number, name?: string, status?: string, observe: any = 'body', headers: Headers = {}): Observable<any> {
257-
if (!petId){
257+
if (petId === null || petId === undefined){
258258
throw new Error('Required parameter petId was null or undefined when calling updatePetWithForm.');
259259
}
260260

@@ -297,7 +297,7 @@ export class PetService {
297297
public uploadFile(petId: number, additionalMetadata?: string, file?: Blob, observe?: 'body', headers?: Headers): Observable<ApiResponse>;
298298
public uploadFile(petId: number, additionalMetadata?: string, file?: Blob, observe?: 'response', headers?: Headers): Observable<HttpResponse<ApiResponse>>;
299299
public uploadFile(petId: number, additionalMetadata?: string, file?: Blob, observe: any = 'body', headers: Headers = {}): Observable<any> {
300-
if (!petId){
300+
if (petId === null || petId === undefined){
301301
throw new Error('Required parameter petId was null or undefined when calling uploadFile.');
302302
}
303303

samples/client/petstore/typescript-inversify/api/store.service.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class StoreService {
4545
public deleteOrder(orderId: string, observe?: 'body', headers?: Headers): Observable<any>;
4646
public deleteOrder(orderId: string, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
4747
public deleteOrder(orderId: string, observe: any = 'body', headers: Headers = {}): Observable<any> {
48-
if (!orderId){
48+
if (orderId === null || orderId === undefined){
4949
throw new Error('Required parameter orderId was null or undefined when calling deleteOrder.');
5050
}
5151

@@ -94,11 +94,11 @@ export class StoreService {
9494
public getOrderById(orderId: number, observe?: 'body', headers?: Headers): Observable<Order>;
9595
public getOrderById(orderId: number, observe?: 'response', headers?: Headers): Observable<HttpResponse<Order>>;
9696
public getOrderById(orderId: number, observe: any = 'body', headers: Headers = {}): Observable<any> {
97-
if (!orderId){
97+
if (orderId === null || orderId === undefined){
9898
throw new Error('Required parameter orderId was null or undefined when calling getOrderById.');
9999
}
100100

101-
headers['Accept'] = 'application/xml';
101+
headers['Accept'] = 'application/xml, application/json';
102102

103103
const response: Observable<HttpResponse<Order>> = this.httpClient.get(`${this.basePath}/store/order/${encodeURIComponent(String(orderId))}`, headers);
104104
if (observe == 'body') {
@@ -119,11 +119,11 @@ export class StoreService {
119119
public placeOrder(body: Order, observe?: 'body', headers?: Headers): Observable<Order>;
120120
public placeOrder(body: Order, observe?: 'response', headers?: Headers): Observable<HttpResponse<Order>>;
121121
public placeOrder(body: Order, observe: any = 'body', headers: Headers = {}): Observable<any> {
122-
if (!body){
122+
if (body === null || body === undefined){
123123
throw new Error('Required parameter body was null or undefined when calling placeOrder.');
124124
}
125125

126-
headers['Accept'] = 'application/xml';
126+
headers['Accept'] = 'application/xml, application/json';
127127
headers['Content-Type'] = 'application/json';
128128

129129
const response: Observable<HttpResponse<Order>> = this.httpClient.post(`${this.basePath}/store/order`, body , headers);

samples/client/petstore/typescript-inversify/api/user.service.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class UserService {
4545
public createUser(body: User, observe?: 'body', headers?: Headers): Observable<any>;
4646
public createUser(body: User, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
4747
public createUser(body: User, observe: any = 'body', headers: Headers = {}): Observable<any> {
48-
if (!body){
48+
if (body === null || body === undefined){
4949
throw new Error('Required parameter body was null or undefined when calling createUser.');
5050
}
5151

@@ -71,7 +71,7 @@ export class UserService {
7171
public createUsersWithArrayInput(body: Array<User>, observe?: 'body', headers?: Headers): Observable<any>;
7272
public createUsersWithArrayInput(body: Array<User>, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
7373
public createUsersWithArrayInput(body: Array<User>, observe: any = 'body', headers: Headers = {}): Observable<any> {
74-
if (!body){
74+
if (body === null || body === undefined){
7575
throw new Error('Required parameter body was null or undefined when calling createUsersWithArrayInput.');
7676
}
7777

@@ -97,7 +97,7 @@ export class UserService {
9797
public createUsersWithListInput(body: Array<User>, observe?: 'body', headers?: Headers): Observable<any>;
9898
public createUsersWithListInput(body: Array<User>, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
9999
public createUsersWithListInput(body: Array<User>, observe: any = 'body', headers: Headers = {}): Observable<any> {
100-
if (!body){
100+
if (body === null || body === undefined){
101101
throw new Error('Required parameter body was null or undefined when calling createUsersWithListInput.');
102102
}
103103

@@ -123,7 +123,7 @@ export class UserService {
123123
public deleteUser(username: string, observe?: 'body', headers?: Headers): Observable<any>;
124124
public deleteUser(username: string, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
125125
public deleteUser(username: string, observe: any = 'body', headers: Headers = {}): Observable<any> {
126-
if (!username){
126+
if (username === null || username === undefined){
127127
throw new Error('Required parameter username was null or undefined when calling deleteUser.');
128128
}
129129

@@ -148,11 +148,11 @@ export class UserService {
148148
public getUserByName(username: string, observe?: 'body', headers?: Headers): Observable<User>;
149149
public getUserByName(username: string, observe?: 'response', headers?: Headers): Observable<HttpResponse<User>>;
150150
public getUserByName(username: string, observe: any = 'body', headers: Headers = {}): Observable<any> {
151-
if (!username){
151+
if (username === null || username === undefined){
152152
throw new Error('Required parameter username was null or undefined when calling getUserByName.');
153153
}
154154

155-
headers['Accept'] = 'application/xml';
155+
headers['Accept'] = 'application/xml, application/json';
156156

157157
const response: Observable<HttpResponse<User>> = this.httpClient.get(`${this.basePath}/user/${encodeURIComponent(String(username))}`, headers);
158158
if (observe == 'body') {
@@ -174,11 +174,11 @@ export class UserService {
174174
public loginUser(username: string, password: string, observe?: 'body', headers?: Headers): Observable<string>;
175175
public loginUser(username: string, password: string, observe?: 'response', headers?: Headers): Observable<HttpResponse<string>>;
176176
public loginUser(username: string, password: string, observe: any = 'body', headers: Headers = {}): Observable<any> {
177-
if (!username){
177+
if (username === null || username === undefined){
178178
throw new Error('Required parameter username was null or undefined when calling loginUser.');
179179
}
180180

181-
if (!password){
181+
if (password === null || password === undefined){
182182
throw new Error('Required parameter password was null or undefined when calling loginUser.');
183183
}
184184

@@ -190,7 +190,7 @@ export class UserService {
190190
queryParameters.push("password="+encodeURIComponent(String(password)));
191191
}
192192

193-
headers['Accept'] = 'application/xml';
193+
headers['Accept'] = 'application/xml, application/json';
194194

195195
const response: Observable<HttpResponse<string>> = this.httpClient.get(`${this.basePath}/user/login?${queryParameters.join('&')}`, headers);
196196
if (observe == 'body') {
@@ -232,11 +232,11 @@ export class UserService {
232232
public updateUser(username: string, body: User, observe?: 'body', headers?: Headers): Observable<any>;
233233
public updateUser(username: string, body: User, observe?: 'response', headers?: Headers): Observable<HttpResponse<any>>;
234234
public updateUser(username: string, body: User, observe: any = 'body', headers: Headers = {}): Observable<any> {
235-
if (!username){
235+
if (username === null || username === undefined){
236236
throw new Error('Required parameter username was null or undefined when calling updateUser.');
237237
}
238238

239-
if (!body){
239+
if (body === null || body === undefined){
240240
throw new Error('Required parameter body was null or undefined when calling updateUser.');
241241
}
242242

samples/client/petstore/typescript-inversify/model/inlineObject.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* OpenAPI Petstore
33
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
44
*
5-
* OpenAPI spec version: 1.0.0
5+
* The version of the OpenAPI document: 1.0.0
66
*
77
*
88
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

samples/client/petstore/typescript-inversify/model/inlineObject1.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* OpenAPI Petstore
33
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
44
*
5-
* OpenAPI spec version: 1.0.0
5+
* The version of the OpenAPI document: 1.0.0
66
*
77
*
88
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

0 commit comments

Comments
 (0)