Skip to content

Commit 025d53e

Browse files
authored
feat: support request body encoding option (#108)
1 parent 3530287 commit 025d53e

21 files changed

+2704
-4
lines changed

src/code-templates/_shared/ApiClientInterface.ts

+53
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,50 @@ const createObjectLikeInterface = (factory: TsGenerator.Factory.Type) => {
105105
});
106106
};
107107

108+
const createEncodingInterface = (factory: TsGenerator.Factory.Type) => {
109+
return factory.InterfaceDeclaration.create({
110+
export: true,
111+
name: "Encoding",
112+
members: [
113+
factory.PropertySignature.create({
114+
name: "contentType",
115+
optional: true,
116+
type: factory.TypeReferenceNode.create({
117+
name: "string",
118+
}),
119+
}),
120+
factory.PropertySignature.create({
121+
name: "headers",
122+
optional: true,
123+
type: factory.TypeReferenceNode.create({
124+
name: "Record<string, any>",
125+
}),
126+
}),
127+
factory.PropertySignature.create({
128+
name: "style",
129+
optional: true,
130+
type: factory.TypeReferenceNode.create({
131+
name: "string",
132+
}),
133+
}),
134+
factory.PropertySignature.create({
135+
name: "explode",
136+
optional: true,
137+
type: factory.TypeReferenceNode.create({
138+
name: "boolean",
139+
}),
140+
}),
141+
factory.PropertySignature.create({
142+
name: "allowReserved",
143+
optional: true,
144+
type: factory.TypeReferenceNode.create({
145+
name: "boolean",
146+
}),
147+
}),
148+
],
149+
});
150+
};
151+
108152
export const create = (factory: TsGenerator.Factory.Type, list: CodeGenerator.Params[], option: Option): ts.Statement[] => {
109153
const objectLikeOrAnyType = factory.UnionTypeNode.create({
110154
typeNodes: [
@@ -117,12 +161,15 @@ export const create = (factory: TsGenerator.Factory.Type, list: CodeGenerator.Pa
117161
],
118162
});
119163

164+
const encodingInterface = createEncodingInterface(factory);
165+
120166
const requestArgs = factory.ParameterDeclaration.create({
121167
name: "requestArgs",
122168
type: factory.TypeReferenceNode.create({
123169
name: "RequestArgs",
124170
}),
125171
});
172+
126173
const options = factory.ParameterDeclaration.create({
127174
name: "options",
128175
optional: true,
@@ -197,6 +244,11 @@ export const create = (factory: TsGenerator.Factory.Type, list: CodeGenerator.Pa
197244
optional: false,
198245
type: objectLikeOrAnyType,
199246
}),
247+
factory.PropertySignature.create({
248+
name: `requestBodyEncoding`,
249+
optional: true,
250+
type: factory.TypeReferenceNode.create({ name: "Record<string, Encoding>" }),
251+
}),
200252
factory.PropertySignature.create({
201253
name: `queryParameters`,
202254
optional: false,
@@ -219,6 +271,7 @@ export const create = (factory: TsGenerator.Factory.Type, list: CodeGenerator.Pa
219271
...createQueryParamsDeclarations(factory),
220272
createSuccessResponseTypeAlias("SuccessResponses", factory, successResponseNames),
221273
errorResponseNamespace,
274+
encodingInterface,
222275
requestArgsInterfaceDeclaration,
223276
factory.InterfaceDeclaration.create({
224277
export: true,

src/code-templates/_shared/MethodBody/CallRequest.ts

+22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@ export interface Params {
1010
hasRequestBody: boolean;
1111
}
1212

13+
/**
14+
*
15+
* const encodingMap = {
16+
* "application/json": {},
17+
* "application/x-www-form-urlencoded": {},
18+
* }
19+
*/
20+
const createEncodingParams = (factory: TsGenerator.Factory.Type, params: CodeGenerator.Params): ts.Expression => {
21+
const content = params.operationParams.requestBody?.content;
22+
if (!content) {
23+
return factory.Identifier.create({ name: "undefined" });
24+
}
25+
if (params.convertedParams.has2OrMoreRequestContentTypes) {
26+
return factory.Identifier.create({ name: `requestEncodings[params.headers["Content-Type"]]` });
27+
}
28+
return factory.Identifier.create({ name: `requestEncodings["${params.convertedParams.requestFirstContentType}"]` });
29+
};
30+
1331
/**
1432
* this.apiClient.request("GET", url, requestBody, headers, queryParameters);
1533
*/
@@ -41,6 +59,10 @@ export const create = (factory: TsGenerator.Factory.Type, params: CodeGenerator.
4159
? Utils.generateVariableIdentifier(factory, "params.requestBody")
4260
: factory.Identifier.create({ name: "undefined" }),
4361
}),
62+
factory.PropertyAssignment.create({
63+
name: "requestBodyEncoding",
64+
initializer: createEncodingParams(factory, params),
65+
}),
4466
factory.PropertyAssignment.create({
4567
name: "queryParameters",
4668
initializer: convertedParams.hasQueryParameters

src/code-templates/_shared/MethodBody/index.ts

+46-1
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,26 @@ import * as HeaderParameter from "./HeaderParameter";
99
import * as PathParameter from "./PathParameter";
1010
import * as QueryParameter from "./QueryParameter";
1111
import type { MethodType } from "./types";
12+
import { Encoding } from "../../../typedef/OpenApi";
1213

1314
export interface Params$GenerateUrl {
1415
urlTemplate: Utils.Params$TemplateExpression;
1516
}
1617

18+
type EncodingMap = Record<string, Encoding>;
19+
1720
export const create = (factory: TsGenerator.Factory.Type, params: CodeGenerator.Params, methodType: MethodType): ts.Statement[] => {
1821
const statements: ts.Statement[] = [];
19-
const { convertedParams } = params;
22+
const { convertedParams, operationParams } = params;
2023
const { pickedParameters } = convertedParams;
2124

2225
// Generate Path Parameter
2326
const pathParameters = pickedParameters.filter(PathParameter.isPathParameter);
2427
statements.push(PathParameter.create(factory, params.operationParams.requestUri, pathParameters, methodType));
2528

29+
/**
30+
* Create Variable: const header = {};
31+
*/
2632
const initialHeaderObject: Utils.LiteralExpressionObject = {};
2733
if (convertedParams.has2OrMoreRequestContentTypes) {
2834
initialHeaderObject["Content-Type"] = {
@@ -59,6 +65,45 @@ export const create = (factory: TsGenerator.Factory.Type, params: CodeGenerator.
5965
}),
6066
);
6167

68+
/**
69+
* Create Variable: const requestEncoding = {};
70+
*/
71+
const content = operationParams.requestBody?.content;
72+
if (content) {
73+
const encodingMap = Object.keys(content).reduce<EncodingMap>((all, key) => {
74+
const { encoding } = content[key];
75+
if (!encoding) {
76+
return all;
77+
}
78+
return { ...all, [key]: encoding };
79+
}, {});
80+
let identifier: ts.Identifier | undefined;
81+
if (convertedParams.has2OrMoreRequestContentTypes) {
82+
identifier = factory.Identifier.create({
83+
name: JSON.stringify(encodingMap, null, 2),
84+
});
85+
} else if (convertedParams.requestFirstContentType) {
86+
identifier = factory.Identifier.create({
87+
name: JSON.stringify({ [convertedParams.requestFirstContentType]: encodingMap[convertedParams.requestFirstContentType] }, null, 2),
88+
});
89+
}
90+
const requestEncodingsVariableStatement = factory.VariableStatement.create({
91+
declarationList: factory.VariableDeclarationList.create({
92+
flag: "const",
93+
declarations: [
94+
factory.VariableDeclaration.create({
95+
name: "requestEncodings",
96+
initializer: identifier,
97+
}),
98+
],
99+
}),
100+
});
101+
102+
if (identifier && Object.keys(encodingMap).length > 0) {
103+
statements.push(requestEncodingsVariableStatement);
104+
}
105+
}
106+
62107
// Generate Query Parameter
63108
if (convertedParams.hasQueryParameters) {
64109
const queryParameter = pickedParameters.filter(item => item.in === "query");

src/meta.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export const Name = "@himenon/openapi-typescript-code-generator";
2-
export const Version = "0.23.0";
2+
export const Version = "0.23.0";

test/__tests__/class/__snapshots__/argo-rollout-test.ts.snap

+20
Original file line numberDiff line numberDiff line change
@@ -3826,11 +3826,19 @@ export namespace ErrorResponse {
38263826
export type RolloutService_UndoRollout = void;
38273827
export type RolloutService_Version = void;
38283828
}
3829+
export interface Encoding {
3830+
contentType?: string;
3831+
headers?: Record<string, any>;
3832+
style?: string;
3833+
explode?: boolean;
3834+
allowReserved?: boolean;
3835+
}
38293836
export interface RequestArgs {
38303837
httpMethod: HttpMethod;
38313838
url: string;
38323839
headers: ObjectLike | any;
38333840
requestBody: ObjectLike | any;
3841+
requestBodyEncoding?: Record<string, Encoding>;
38343842
queryParameters: QueryParameters | undefined;
38353843
}
38363844
export interface ApiClient<RequestOption> {
@@ -3849,6 +3857,7 @@ export class Client<RequestOption> {
38493857
url: url,
38503858
headers: headers,
38513859
requestBody: undefined,
3860+
requestBodyEncoding: undefined,
38523861
queryParameters: undefined
38533862
}, option);
38543863
}
@@ -3862,6 +3871,7 @@ export class Client<RequestOption> {
38623871
url: url,
38633872
headers: headers,
38643873
requestBody: undefined,
3874+
requestBodyEncoding: undefined,
38653875
queryParameters: undefined
38663876
}, option);
38673877
}
@@ -3875,6 +3885,7 @@ export class Client<RequestOption> {
38753885
url: url,
38763886
headers: headers,
38773887
requestBody: undefined,
3888+
requestBodyEncoding: undefined,
38783889
queryParameters: undefined
38793890
}, option);
38803891
}
@@ -3889,6 +3900,7 @@ export class Client<RequestOption> {
38893900
url: url,
38903901
headers: headers,
38913902
requestBody: params.requestBody,
3903+
requestBodyEncoding: requestEncodings["application/json"],
38923904
queryParameters: undefined
38933905
}, option);
38943906
}
@@ -3902,6 +3914,7 @@ export class Client<RequestOption> {
39023914
url: url,
39033915
headers: headers,
39043916
requestBody: undefined,
3917+
requestBodyEncoding: undefined,
39053918
queryParameters: undefined
39063919
}, option);
39073920
}
@@ -3915,6 +3928,7 @@ export class Client<RequestOption> {
39153928
url: url,
39163929
headers: headers,
39173930
requestBody: undefined,
3931+
requestBodyEncoding: undefined,
39183932
queryParameters: undefined
39193933
}, option);
39203934
}
@@ -3929,6 +3943,7 @@ export class Client<RequestOption> {
39293943
url: url,
39303944
headers: headers,
39313945
requestBody: params.requestBody,
3946+
requestBodyEncoding: requestEncodings["application/json"],
39323947
queryParameters: undefined
39333948
}, option);
39343949
}
@@ -3943,6 +3958,7 @@ export class Client<RequestOption> {
39433958
url: url,
39443959
headers: headers,
39453960
requestBody: params.requestBody,
3961+
requestBodyEncoding: requestEncodings["application/json"],
39463962
queryParameters: undefined
39473963
}, option);
39483964
}
@@ -3957,6 +3973,7 @@ export class Client<RequestOption> {
39573973
url: url,
39583974
headers: headers,
39593975
requestBody: params.requestBody,
3976+
requestBodyEncoding: requestEncodings["application/json"],
39603977
queryParameters: undefined
39613978
}, option);
39623979
}
@@ -3971,6 +3988,7 @@ export class Client<RequestOption> {
39713988
url: url,
39723989
headers: headers,
39733990
requestBody: params.requestBody,
3991+
requestBodyEncoding: requestEncodings["application/json"],
39743992
queryParameters: undefined
39753993
}, option);
39763994
}
@@ -3985,6 +4003,7 @@ export class Client<RequestOption> {
39854003
url: url,
39864004
headers: headers,
39874005
requestBody: params.requestBody,
4006+
requestBodyEncoding: requestEncodings["application/json"],
39884007
queryParameters: undefined
39894008
}, option);
39904009
}
@@ -3998,6 +4017,7 @@ export class Client<RequestOption> {
39984017
url: url,
39994018
headers: headers,
40004019
requestBody: undefined,
4020+
requestBodyEncoding: undefined,
40014021
queryParameters: undefined
40024022
}, option);
40034023
}

test/__tests__/class/__snapshots__/format.domain.ts.snap

+8
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,19 @@ export interface QueryParameters {
4343
}
4444
export type SuccessResponses = void;
4545
export namespace ErrorResponse { }
46+
export interface Encoding {
47+
contentType?: string;
48+
headers?: Record<string, any>;
49+
style?: string;
50+
explode?: boolean;
51+
allowReserved?: boolean;
52+
}
4653
export interface RequestArgs {
4754
httpMethod: HttpMethod;
4855
url: string;
4956
headers: ObjectLike | any;
5057
requestBody: ObjectLike | any;
58+
requestBodyEncoding?: Record<string, Encoding>;
5159
queryParameters: QueryParameters | undefined;
5260
}
5361
export interface ApiClient<RequestOption> {

0 commit comments

Comments
 (0)