Skip to content

Commit 711a210

Browse files
clemens-smartparkingmacjohnny
authored andcommitted
typescript-node: form data file (#3967)
* [typescript][node]: Add options to specify a from data file Be able to specify file options as described on https://github.com/request/request in the 'multipart/form-data (Multipart Form Uploads)' section). Related to #3944 Fix file return type * [typescript][node]: Fix use of applyLocalTypeMapping Previous call to applyLocalTypeMapping didn't had any effect. * [typescript][node]: Update samples
1 parent f13043e commit 711a210

File tree

11 files changed

+79
-19
lines changed

11 files changed

+79
-19
lines changed

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

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
package org.openapitools.codegen.languages;
1919

20+
import io.swagger.v3.oas.models.Operation;
2021
import io.swagger.v3.oas.models.media.Schema;
22+
import io.swagger.v3.oas.models.responses.ApiResponse;
2123
import org.openapitools.codegen.*;
2224
import org.openapitools.codegen.utils.ModelUtils;
2325
import org.slf4j.Logger;
@@ -40,8 +42,12 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen
4042
public TypeScriptNodeClientCodegen() {
4143
super();
4244

43-
typeMapping.put("file", "Buffer");
45+
typeMapping.put("file", "RequestFile");
46+
// RequestFile is defined as: `type RequestFile = string | Buffer | ReadStream | RequestDetailedFile;`
4447
languageSpecificPrimitives.add("Buffer");
48+
languageSpecificPrimitives.add("ReadStream");
49+
languageSpecificPrimitives.add("RequestDetailedFile");
50+
languageSpecificPrimitives.add("RequestFile");
4551

4652
// clear import mapping (from default generator) as TS does not use it
4753
// at the moment
@@ -70,19 +76,35 @@ public String getHelp() {
7076

7177
@Override
7278
public boolean isDataTypeFile(final String dataType) {
73-
return "Buffer".equals(dataType);
79+
return dataType != null && dataType.equals("RequestFile");
7480
}
7581

7682
@Override
7783
public String getTypeDeclaration(Schema p) {
7884
if (ModelUtils.isFileSchema(p)) {
79-
return "Buffer";
85+
// There are two file types:
86+
// 1) RequestFile: the parameter for the request lib when uploading a file
87+
// (https://github.com/request/request#multipartform-data-multipart-form-uploads)
88+
// 2) Buffer: for downloading files.
89+
// Use RequestFile as a default. The return type is fixed to Buffer in handleMethodResponse.
90+
return "RequestFile";
8091
} else if (ModelUtils.isBinarySchema(p)) {
8192
return "Buffer";
8293
}
8394
return super.getTypeDeclaration(p);
8495
}
85-
96+
97+
@Override
98+
protected void handleMethodResponse(Operation operation, Map<String, Schema> schemas, CodegenOperation op,
99+
ApiResponse methodResponse) {
100+
super.handleMethodResponse(operation, schemas, op, methodResponse);
101+
102+
// see comment in getTypeDeclaration
103+
if (op.isResponseFile) {
104+
op.returnType = "Buffer";
105+
}
106+
}
107+
86108
@Override
87109
public String toApiName(String name) {
88110
if (name.length() == 0) {
@@ -239,13 +261,12 @@ public String getSchemaType(Schema p) {
239261
if (isLanguagePrimitive(openAPIType) || isLanguageGenericType(openAPIType)) {
240262
return openAPIType;
241263
}
242-
applyLocalTypeMapping(openAPIType);
243-
return openAPIType;
264+
return applyLocalTypeMapping(openAPIType);
244265
}
245266

246267
private String applyLocalTypeMapping(String type) {
247268
if (typeMapping.containsKey(type)) {
248-
type = typeMapping.get(type);
269+
return typeMapping.get(type);
249270
}
250271
return type;
251272
}

modules/openapi-generator/src/main/resources/typescript-node/api-all.mustache

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,25 @@ import { {{ classname }} } from './{{ classFilename }}';
88
export * from './{{ classFilename }}Interface'
99
{{/withInterfaces}}
1010
{{/apis}}
11-
import http = require('http');
11+
import * as fs from 'fs';
12+
import * as http from 'http';
13+
1214
export class HttpError extends Error {
1315
constructor (public response: http.{{#supportsES6}}IncomingMessage{{/supportsES6}}{{^supportsES6}}ClientResponse{{/supportsES6}}, public body: any, public statusCode?: number) {
1416
super('HTTP request failed');
1517
this.name = 'HttpError';
1618
}
1719
}
20+
21+
export interface RequestDetailedFile {
22+
value: Buffer;
23+
options?: {
24+
filename?: string;
25+
contentType?: string;
26+
}
27+
}
28+
29+
export type RequestFile = string | Buffer | fs.ReadStream | RequestDetailedFile;
30+
1831
export const APIS = [{{#apis}}{{#operations}}{{ classname }}{{/operations}}{{^-last}}, {{/-last}}{{/apis}}];
1932
{{/apiInfo}}

modules/openapi-generator/src/main/resources/typescript-node/api-single.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { ObjectSerializer, Authentication, VoidAuth } from '../model/models';
1212
import { HttpBasicAuth, ApiKeyAuth, OAuth } from '../model/models';
1313
{{/hasAuthMethods}}
1414

15-
import { HttpError } from './apis';
15+
import { HttpError, RequestFile } from './apis';
1616

1717
let defaultBasePath = '{{{basePath}}}';
1818

samples/client/petstore/typescript-node/default/api/apis.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,24 @@ export * from './storeApi';
44
import { StoreApi } from './storeApi';
55
export * from './userApi';
66
import { UserApi } from './userApi';
7-
import http = require('http');
7+
import * as fs from 'fs';
8+
import * as http from 'http';
9+
810
export class HttpError extends Error {
911
constructor (public response: http.ClientResponse, public body: any, public statusCode?: number) {
1012
super('HTTP request failed');
1113
this.name = 'HttpError';
1214
}
1315
}
16+
17+
export interface RequestDetailedFile {
18+
value: Buffer;
19+
options?: {
20+
filename?: string;
21+
contentType?: string;
22+
}
23+
}
24+
25+
export type RequestFile = string | Buffer | fs.ReadStream | RequestDetailedFile;
26+
1427
export const APIS = [PetApi, StoreApi, UserApi];

samples/client/petstore/typescript-node/default/api/petApi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { Pet } from '../model/pet';
2020
import { ObjectSerializer, Authentication, VoidAuth } from '../model/models';
2121
import { HttpBasicAuth, ApiKeyAuth, OAuth } from '../model/models';
2222

23-
import { HttpError } from './apis';
23+
import { HttpError, RequestFile } from './apis';
2424

2525
let defaultBasePath = 'http://petstore.swagger.io/v2';
2626

@@ -528,7 +528,7 @@ export class PetApi {
528528
* @param additionalMetadata Additional data to pass to server
529529
* @param file file to upload
530530
*/
531-
public async uploadFile (petId: number, additionalMetadata?: string, file?: Buffer, options: {headers: {[name: string]: string}} = {headers: {}}) : Promise<{ response: http.ClientResponse; body: ApiResponse; }> {
531+
public async uploadFile (petId: number, additionalMetadata?: string, file?: RequestFile, options: {headers: {[name: string]: string}} = {headers: {}}) : Promise<{ response: http.ClientResponse; body: ApiResponse; }> {
532532
const localVarPath = this.basePath + '/pet/{petId}/uploadImage'
533533
.replace('{' + 'petId' + '}', encodeURIComponent(String(petId)));
534534
let localVarQueryParameters: any = {};

samples/client/petstore/typescript-node/default/api/storeApi.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { Order } from '../model/order';
1919
import { ObjectSerializer, Authentication, VoidAuth } from '../model/models';
2020
import { HttpBasicAuth, ApiKeyAuth, OAuth } from '../model/models';
2121

22-
import { HttpError } from './apis';
22+
import { HttpError, RequestFile } from './apis';
2323

2424
let defaultBasePath = 'http://petstore.swagger.io/v2';
2525

samples/client/petstore/typescript-node/default/api/userApi.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { User } from '../model/user';
1818

1919
import { ObjectSerializer, Authentication, VoidAuth } from '../model/models';
2020

21-
import { HttpError } from './apis';
21+
import { HttpError, RequestFile } from './apis';
2222

2323
let defaultBasePath = 'http://petstore.swagger.io/v2';
2424

samples/client/petstore/typescript-node/npm/api/apis.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,24 @@ export * from './storeApi';
44
import { StoreApi } from './storeApi';
55
export * from './userApi';
66
import { UserApi } from './userApi';
7-
import http = require('http');
7+
import * as fs from 'fs';
8+
import * as http from 'http';
9+
810
export class HttpError extends Error {
911
constructor (public response: http.ClientResponse, public body: any, public statusCode?: number) {
1012
super('HTTP request failed');
1113
this.name = 'HttpError';
1214
}
1315
}
16+
17+
export interface RequestDetailedFile {
18+
value: Buffer;
19+
options?: {
20+
filename?: string;
21+
contentType?: string;
22+
}
23+
}
24+
25+
export type RequestFile = string | Buffer | fs.ReadStream | RequestDetailedFile;
26+
1427
export const APIS = [PetApi, StoreApi, UserApi];

samples/client/petstore/typescript-node/npm/api/petApi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { Pet } from '../model/pet';
2020
import { ObjectSerializer, Authentication, VoidAuth } from '../model/models';
2121
import { HttpBasicAuth, ApiKeyAuth, OAuth } from '../model/models';
2222

23-
import { HttpError } from './apis';
23+
import { HttpError, RequestFile } from './apis';
2424

2525
let defaultBasePath = 'http://petstore.swagger.io/v2';
2626

@@ -528,7 +528,7 @@ export class PetApi {
528528
* @param additionalMetadata Additional data to pass to server
529529
* @param file file to upload
530530
*/
531-
public async uploadFile (petId: number, additionalMetadata?: string, file?: Buffer, options: {headers: {[name: string]: string}} = {headers: {}}) : Promise<{ response: http.ClientResponse; body: ApiResponse; }> {
531+
public async uploadFile (petId: number, additionalMetadata?: string, file?: RequestFile, options: {headers: {[name: string]: string}} = {headers: {}}) : Promise<{ response: http.ClientResponse; body: ApiResponse; }> {
532532
const localVarPath = this.basePath + '/pet/{petId}/uploadImage'
533533
.replace('{' + 'petId' + '}', encodeURIComponent(String(petId)));
534534
let localVarQueryParameters: any = {};

samples/client/petstore/typescript-node/npm/api/storeApi.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { Order } from '../model/order';
1919
import { ObjectSerializer, Authentication, VoidAuth } from '../model/models';
2020
import { HttpBasicAuth, ApiKeyAuth, OAuth } from '../model/models';
2121

22-
import { HttpError } from './apis';
22+
import { HttpError, RequestFile } from './apis';
2323

2424
let defaultBasePath = 'http://petstore.swagger.io/v2';
2525

0 commit comments

Comments
 (0)