Skip to content

Commit e44c29b

Browse files
committed
chore(codegen): add error response names
1 parent d3f64ad commit e44c29b

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

src/Converter/v3/Generator.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const extractPickedParameter = (parameter: OpenApi.Parameter): PickedParameter =
1414
};
1515
};
1616

17-
const extractSuccessStatusCode = (responses: { [statusCode: string]: OpenApi.Response }): string[] => {
17+
const extractResponseNamesByStatusCode = (type: "success" | "error", responses: { [statusCode: string]: OpenApi.Response }): string[] => {
1818
const statusCodeList: string[] = [];
1919
Object.entries(responses || {}).forEach(([statusCodeLike, response]) => {
2020
// ContentTypeの定義が存在しない場合はstatusCodeを読み取らない
@@ -23,8 +23,14 @@ const extractSuccessStatusCode = (responses: { [statusCode: string]: OpenApi.Res
2323
}
2424
if (typeof statusCodeLike === "string") {
2525
const statusCodeNumberValue = parseInt(statusCodeLike, 10);
26-
if (200 <= statusCodeNumberValue && statusCodeNumberValue < 300) {
27-
statusCodeList.push(statusCodeNumberValue.toString());
26+
if (type === "success") {
27+
if (200 <= statusCodeNumberValue && statusCodeNumberValue < 300) {
28+
statusCodeList.push(statusCodeNumberValue.toString());
29+
}
30+
} else if (type === "error") {
31+
if (400 <= statusCodeNumberValue && statusCodeNumberValue < 600) {
32+
statusCodeList.push(statusCodeNumberValue.toString());
33+
}
2834
}
2935
}
3036
});
@@ -37,7 +43,7 @@ const getRequestContentTypeList = (requestBody: OpenApi.RequestBody): string[] =
3743

3844
const getSuccessResponseContentTypeList = (responses: { [statusCode: string]: OpenApi.Response }): string[] => {
3945
let contentTypeList: string[] = [];
40-
extractSuccessStatusCode(responses).forEach(statusCode => {
46+
extractResponseNamesByStatusCode("success", responses).forEach(statusCode => {
4147
const response = responses[statusCode];
4248
contentTypeList = contentTypeList.concat(Object.keys(response.content || {}));
4349
});
@@ -55,7 +61,10 @@ const generateCodeGeneratorParamsList = (store: Store.Type, converterContext: Co
5561
const operationState = store.getNoReferenceOperationState();
5662
const params: CodeGeneratorParams[] = [];
5763
Object.entries(operationState).forEach(([operationId, item]) => {
58-
const responseSuccessNames = extractSuccessStatusCode(item.responses).map(statusCode =>
64+
const responseSuccessNames = extractResponseNamesByStatusCode("success", item.responses).map(statusCode =>
65+
converterContext.generateResponseName(operationId, statusCode),
66+
);
67+
const responseErrorNames = extractResponseNamesByStatusCode("error", item.responses).map(statusCode =>
5968
converterContext.generateResponseName(operationId, statusCode),
6069
);
6170
const requestContentTypeList = item.requestBody ? getRequestContentTypeList(item.requestBody) : [];
@@ -65,6 +74,7 @@ const generateCodeGeneratorParamsList = (store: Store.Type, converterContext: Co
6574

6675
const formatParams: CodeGeneratorParams = {
6776
operationId: operationId,
77+
escapedOperationId: converterContext.escapeOperationIdText(operationId),
6878
rawRequestUri: item.requestUri,
6979
httpMethod: item.httpMethod,
7080
argumentParamsTypeDeclaration: converterContext.generateArgumentParamsTypeDeclaration(operationId),
@@ -88,6 +98,7 @@ const generateCodeGeneratorParamsList = (store: Store.Type, converterContext: Co
8898
responseSuccessNames: responseSuccessNames,
8999
responseFirstSuccessName: responseSuccessNames.length === 1 ? responseSuccessNames[0] : undefined,
90100
has2OrMoreSuccessNames: hasOver2SuccessNames,
101+
responseErrorNames: responseErrorNames,
91102
// Response Success Content Type
92103
successResponseContentTypes: responseSuccessContentTypes,
93104
successResponseFirstContentType: responseSuccessContentTypes.length === 1 ? responseSuccessContentTypes[0] : undefined,

src/Converter/v3/types/CodeGeneratorParams.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export type PickedParameter = Pick<OpenApi.Parameter, "name" | "in" | "required"
44

55
export interface CodeGeneratorParams {
66
operationId: string;
7+
escapedOperationId: string;
78
httpMethod: string; // get, post, put, delete ...etc
89
rawRequestUri: string;
910
functionName: string;
@@ -19,6 +20,8 @@ export interface CodeGeneratorParams {
1920
requestContentTypes: string[];
2021
requestFirstContentType: string | undefined; // requestContentTypes.length === 1 only
2122
has2OrMoreRequestContentTypes: boolean; // requestContentTypes.length > 1
23+
// Response Error Response Name
24+
responseErrorNames: string[];
2225
// Response Success Name
2326
responseSuccessNames: string[]; // `Response$${operationId}$Status$${statusCode}`[]
2427
responseFirstSuccessName: string | undefined; // responseSuccessNames.length === 1 only

src/DefaultCodeTemplate/ApiClientClass/ApiClientInterface.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,27 @@ import { CodeGeneratorParams } from "../../Converter/v3";
55

66
const httpMethodList: string[] = ["GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD", "PATCH", "TRACE"];
77

8+
const createErrorResponsesTypeAlias = (typeName: string, factory: Factory.Type, errorResponseNames: string[]) => {
9+
if (errorResponseNames.length === 0) {
10+
return factory.TypeAliasDeclaration.create({
11+
export: true,
12+
name: typeName,
13+
type: ts.factory.createToken(ts.SyntaxKind.VoidKeyword),
14+
});
15+
}
16+
return factory.TypeAliasDeclaration.create({
17+
export: true,
18+
name: typeName,
19+
type: factory.UnionTypeNode.create({
20+
typeNodes: errorResponseNames.map(name => {
21+
return factory.TypeReferenceNode.create({
22+
name,
23+
});
24+
}),
25+
}),
26+
});
27+
};
28+
829
const createSuccessResponseTypeAlias = (typeName: string, factory: Factory.Type, successResponseNames: string[]) => {
930
if (successResponseNames.length === 0) {
1031
return factory.TypeAliasDeclaration.create({
@@ -134,6 +155,10 @@ export const create = (factory: Factory.Type, list: CodeGeneratorParams[]): ts.S
134155

135156
const successResponseNames = list.map(item => item.responseSuccessNames).flat();
136157

158+
const errorResponseTypes = list.map(item => {
159+
return createErrorResponsesTypeAlias(`ErrorResponses$${item.escapedOperationId}`, factory, item.responseErrorNames);
160+
});
161+
137162
const functionType = factory.FunctionTypeNode.create({
138163
typeParameters: [
139164
factory.TypeParameterDeclaration.create({
@@ -165,6 +190,7 @@ export const create = (factory: Factory.Type, list: CodeGeneratorParams[]): ts.S
165190
createObjectLikeInterface(factory),
166191
...createQueryParamsDeclarations(factory),
167192
createSuccessResponseTypeAlias("SuccessResponses", factory, successResponseNames),
193+
...errorResponseTypes,
168194
factory.InterfaceDeclaration.create({
169195
export: true,
170196
name: "ApiClient",

0 commit comments

Comments
 (0)