Skip to content

Commit d20682e

Browse files
authored
[typescript-fetch]Bugfix additional properties in multipart requests (#22570)
* Add test-case for additional-properties-in-multipart-issue * Fix multipart requests for container types * Update samples
1 parent 52306b6 commit d20682e

14 files changed

Lines changed: 842 additions & 0 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
generatorName: typescript-fetch
2+
outputDir: samples/client/others/typescript-fetch/additional-properties-in-multipart-issue
3+
inputSpec: modules/openapi-generator/src/test/resources/3_0/typescript-fetch/additional-properties-in-multipart-issue.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/typescript-fetch
5+
additionalProperties:
6+
enumPropertyNaming: "original"
7+
enumUnknownDefaultCase: true

modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,12 @@ export class {{classname}} extends runtime.BaseAPI {
278278
{{/isEnumRef}}
279279
{{^isEnumRef}}
280280
{{^withoutRuntimeChecks}}
281+
{{^isContainer}}
281282
formParams.append('{{baseName}}', new Blob([JSON.stringify({{{dataType}}}ToJSON(requestParameters['{{paramName}}']))], { type: "application/json", }));
283+
{{/isContainer}}
284+
{{#isContainer}}
285+
formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters['{{paramName}}'])], { type: "application/json", }));
286+
{{/isContainer}}
282287
{{/withoutRuntimeChecks}}{{#withoutRuntimeChecks}}
283288
formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters['{{paramName}}'])], { type: "application/json", }));
284289
{{/withoutRuntimeChecks}}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
openapi: 3.0.3
2+
info:
3+
title: Minimal
4+
description: Api to reproduce bug
5+
version: 0.5.1-SNAPSHOT.0
6+
tags:
7+
- name: test
8+
servers:
9+
- url: http://localhost:8080
10+
paths:
11+
"/api/v1/file":
12+
post:
13+
tags:
14+
- file
15+
operationId: createFile
16+
requestBody:
17+
required: true
18+
content:
19+
multipart/form-data:
20+
schema:
21+
$ref: "#/components/schemas/FileUploadRequest"
22+
encoding:
23+
documentBytes:
24+
contentType: "*/*"
25+
properties:
26+
contentType: application/json
27+
responses:
28+
"201":
29+
description: File created successfully
30+
components:
31+
schemas:
32+
FileUploadRequest:
33+
type: object
34+
properties:
35+
documentBytes:
36+
type: string
37+
format: binary
38+
documentType:
39+
type: string
40+
structured:
41+
$ref: '#/components/schemas/StructuredType'
42+
properties:
43+
$ref: '#/components/schemas/TypeMap'
44+
required:
45+
- documentBytes
46+
- documentType
47+
- properties
48+
TypeMap:
49+
type: object
50+
additionalProperties:
51+
type: string
52+
StructuredType:
53+
type: object
54+
properties:
55+
someString:
56+
type: string
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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apis/FileApi.ts
2+
apis/index.ts
3+
docs/FileApi.md
4+
docs/StructuredType.md
5+
index.ts
6+
models/StructuredType.ts
7+
models/index.ts
8+
runtime.ts
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7.19.0-SNAPSHOT
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/* tslint:disable */
2+
/* eslint-disable */
3+
/**
4+
* Minimal
5+
* Api to reproduce bug
6+
*
7+
* The version of the OpenAPI document: 0.5.1-SNAPSHOT.0
8+
*
9+
*
10+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
11+
* https://openapi-generator.tech
12+
* Do not edit the class manually.
13+
*/
14+
15+
16+
import * as runtime from '../runtime';
17+
import type {
18+
StructuredType,
19+
} from '../models/index';
20+
import {
21+
StructuredTypeFromJSON,
22+
StructuredTypeToJSON,
23+
} from '../models/index';
24+
25+
export interface CreateFileRequest {
26+
documentBytes: Blob;
27+
documentType: string;
28+
properties: { [key: string]: string; };
29+
structured?: StructuredType;
30+
}
31+
32+
/**
33+
*
34+
*/
35+
export class FileApi extends runtime.BaseAPI {
36+
37+
/**
38+
*/
39+
async createFileRaw(requestParameters: CreateFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
40+
if (requestParameters['documentBytes'] == null) {
41+
throw new runtime.RequiredError(
42+
'documentBytes',
43+
'Required parameter "documentBytes" was null or undefined when calling createFile().'
44+
);
45+
}
46+
47+
if (requestParameters['documentType'] == null) {
48+
throw new runtime.RequiredError(
49+
'documentType',
50+
'Required parameter "documentType" was null or undefined when calling createFile().'
51+
);
52+
}
53+
54+
if (requestParameters['properties'] == null) {
55+
throw new runtime.RequiredError(
56+
'properties',
57+
'Required parameter "properties" was null or undefined when calling createFile().'
58+
);
59+
}
60+
61+
const queryParameters: any = {};
62+
63+
const headerParameters: runtime.HTTPHeaders = {};
64+
65+
const consumes: runtime.Consume[] = [
66+
{ contentType: 'multipart/form-data' },
67+
];
68+
// @ts-ignore: canConsumeForm may be unused
69+
const canConsumeForm = runtime.canConsumeForm(consumes);
70+
71+
let formParams: { append(param: string, value: any): any };
72+
let useForm = false;
73+
// use FormData to transmit files using content-type "multipart/form-data"
74+
useForm = canConsumeForm;
75+
if (useForm) {
76+
formParams = new FormData();
77+
} else {
78+
formParams = new URLSearchParams();
79+
}
80+
81+
if (requestParameters['documentBytes'] != null) {
82+
formParams.append('documentBytes', requestParameters['documentBytes'] as any);
83+
}
84+
85+
if (requestParameters['documentType'] != null) {
86+
formParams.append('documentType', requestParameters['documentType'] as any);
87+
}
88+
89+
if (requestParameters['structured'] != null) {
90+
formParams.append('structured', new Blob([JSON.stringify(StructuredTypeToJSON(requestParameters['structured']))], { type: "application/json", }));
91+
}
92+
93+
if (requestParameters['properties'] != null) {
94+
formParams.append('properties', new Blob([JSON.stringify(requestParameters['properties'])], { type: "application/json", }));
95+
}
96+
97+
98+
let urlPath = `/api/v1/file`;
99+
100+
const response = await this.request({
101+
path: urlPath,
102+
method: 'POST',
103+
headers: headerParameters,
104+
query: queryParameters,
105+
body: formParams,
106+
}, initOverrides);
107+
108+
return new runtime.VoidApiResponse(response);
109+
}
110+
111+
/**
112+
*/
113+
async createFile(requestParameters: CreateFileRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
114+
await this.createFileRaw(requestParameters, initOverrides);
115+
}
116+
117+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* tslint:disable */
2+
/* eslint-disable */
3+
export * from './FileApi';
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# FileApi
2+
3+
All URIs are relative to *http://localhost:8080*
4+
5+
| Method | HTTP request | Description |
6+
|------------- | ------------- | -------------|
7+
| [**createFile**](FileApi.md#createfile) | **POST** /api/v1/file | |
8+
9+
10+
11+
## createFile
12+
13+
> createFile(documentBytes, documentType, properties, structured)
14+
15+
16+
17+
### Example
18+
19+
```ts
20+
import {
21+
Configuration,
22+
FileApi,
23+
} from '';
24+
import type { CreateFileRequest } from '';
25+
26+
async function example() {
27+
console.log("🚀 Testing SDK...");
28+
const api = new FileApi();
29+
30+
const body = {
31+
// Blob
32+
documentBytes: BINARY_DATA_HERE,
33+
// string
34+
documentType: documentType_example,
35+
// { [key: string]: string; }
36+
properties: ...,
37+
// StructuredType (optional)
38+
structured: ...,
39+
} satisfies CreateFileRequest;
40+
41+
try {
42+
const data = await api.createFile(body);
43+
console.log(data);
44+
} catch (error) {
45+
console.error(error);
46+
}
47+
}
48+
49+
// Run the test
50+
example().catch(console.error);
51+
```
52+
53+
### Parameters
54+
55+
56+
| Name | Type | Description | Notes |
57+
|------------- | ------------- | ------------- | -------------|
58+
| **documentBytes** | `Blob` | | [Defaults to `undefined`] |
59+
| **documentType** | `string` | | [Defaults to `undefined`] |
60+
| **properties** | `{ [key: string]: string; }` | | |
61+
| **structured** | [StructuredType](StructuredType.md) | | [Optional] [Defaults to `undefined`] |
62+
63+
### Return type
64+
65+
`void` (Empty response body)
66+
67+
### Authorization
68+
69+
No authorization required
70+
71+
### HTTP request headers
72+
73+
- **Content-Type**: `multipart/form-data`
74+
- **Accept**: Not defined
75+
76+
77+
### HTTP response details
78+
| Status code | Description | Response headers |
79+
|-------------|-------------|------------------|
80+
| **201** | File created successfully | - |
81+
82+
[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
83+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
# StructuredType
3+
4+
5+
## Properties
6+
7+
Name | Type
8+
------------ | -------------
9+
`someString` | string
10+
11+
## Example
12+
13+
```typescript
14+
import type { StructuredType } from ''
15+
16+
// TODO: Update the object below with actual values
17+
const example = {
18+
"someString": null,
19+
} satisfies StructuredType
20+
21+
console.log(example)
22+
23+
// Convert the instance to a JSON string
24+
const exampleJSON: string = JSON.stringify(example)
25+
console.log(exampleJSON)
26+
27+
// Parse the JSON string back to an object
28+
const exampleParsed = JSON.parse(exampleJSON) as StructuredType
29+
console.log(exampleParsed)
30+
```
31+
32+
[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md)
33+
34+

0 commit comments

Comments
 (0)