Skip to content

Commit 39f80d8

Browse files
committed
Fix required attribute by considering schemas.
Resolves openapi-ts#584
1 parent 4c51afc commit 39f80d8

20 files changed

+218
-111
lines changed

package-lock.json

+14-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@
5454
"version": "npm run build"
5555
},
5656
"dependencies": {
57+
"@types/lodash": "^4.14.168",
5758
"js-yaml": "^4.0.0",
5859
"kleur": "^4.1.3",
60+
"lodash": "^4.17.21",
5961
"meow": "^9.0.0",
6062
"mime": "^2.5.2",
6163
"prettier": "^2.2.1"

src/transform/headers.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { HeaderObject, SchemaFormatter } from "../types";
2-
import { comment, tsReadonly } from "../utils";
1+
import { HeaderObject, SchemaFormatter, SchemaObject, SourceDocument } from "../types";
2+
import { comment, resolveRefIfNeeded, tsReadonly } from "../utils";
33
import { transformSchemaObj } from "./schema";
44

55
export function transformHeaderObjMap(
66
headerMap: Record<string, HeaderObject>,
7-
options: { formatter?: SchemaFormatter; immutableTypes: boolean }
7+
options: { formatter?: SchemaFormatter; immutableTypes: boolean; document: SourceDocument }
88
): string {
99
let output = "";
1010

@@ -14,7 +14,9 @@ export function transformHeaderObjMap(
1414
if (v.description) output += comment(v.description);
1515

1616
const readonly = tsReadonly(options.immutableTypes);
17-
const required = v.required ? "" : "?";
17+
const schema = resolveRefIfNeeded<SchemaObject>(options.document, v.schema);
18+
19+
const required = v.required || (schema != null && schema.default != null) ? "" : "?";
1820

1921
output += ` ${readonly}"${k}"${required}: ${transformSchemaObj(v.schema, options)}\n`;
2022
});

src/transform/index.ts

+12
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
2828
formatter,
2929
immutableTypes,
3030
required: Object.keys(schema),
31+
document: schema,
3132
})}\n}`;
3233
}
3334
case 3: {
3435
return `export interface schemas {\n ${transformSchemaObjMap(schema, {
3536
formatter,
3637
immutableTypes,
3738
required: Object.keys(schema),
39+
document: schema,
3840
})}\n }\n\n`;
3941
}
4042
}
@@ -47,6 +49,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
4749
globalParameters: (schema.components && schema.components.parameters) || schema.parameters,
4850
immutableTypes,
4951
operations,
52+
document: schema,
5053
version,
5154
});
5255
}
@@ -60,6 +63,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
6063
formatter,
6164
immutableTypes,
6265
required: Object.keys(schema.definitions),
66+
document: schema,
6367
})}\n}\n\n`;
6468
}
6569

@@ -70,6 +74,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
7074
formatter,
7175
immutableTypes,
7276
required,
77+
document: schema,
7378
})}\n }\n\n`;
7479
}
7580

@@ -78,6 +83,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
7883
output += `export interface responses {\n ${transformResponsesObj(schema.responses, {
7984
formatter,
8085
immutableTypes,
86+
document: schema,
8187
})}\n }\n\n`;
8288
}
8389
break;
@@ -94,6 +100,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
94100
formatter,
95101
immutableTypes,
96102
required,
103+
document: schema,
97104
})}\n }\n`;
98105
}
99106

@@ -102,6 +109,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
102109
output += ` ${readonly}responses: {\n ${transformResponsesObj(schema.components.responses, {
103110
formatter,
104111
immutableTypes,
112+
document: schema,
105113
})}\n }\n`;
106114
}
107115

@@ -112,6 +120,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
112120
formatter,
113121
immutableTypes,
114122
required,
123+
document: schema,
115124
})}\n }\n`;
116125
}
117126

@@ -120,13 +129,15 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
120129
output += ` ${readonly}requestBodies: {\n ${transformRequestBodies(schema.components.requestBodies, {
121130
formatter,
122131
immutableTypes,
132+
document: schema,
123133
})}\n }\n`;
124134
}
125135

126136
// #/components/headers
127137
if (schema.components.headers) {
128138
output += ` ${readonly}headers: {\n ${transformHeaderObjMap(schema.components.headers, {
129139
formatter,
140+
document: schema,
130141
immutableTypes,
131142
})} }\n`;
132143
}
@@ -145,6 +156,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
145156
pathItem,
146157
globalParameters: (schema.components && schema.components.parameters) || schema.parameters,
147158
immutableTypes,
159+
document: schema,
148160
version,
149161
})}\n }\n`;
150162
});

src/transform/operation.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { OperationObject, ParameterObject, PathItemObject, RequestBody } from "../types";
1+
import { OperationObject, ParameterObject, PathItemObject, RequestBody, SourceDocument } from "../types";
22
import { comment, isRef, transformRef, tsReadonly } from "../utils";
33
import { transformParametersArray } from "./parameters";
44
import { transformResponsesObj } from "./responses";
@@ -10,11 +10,13 @@ export function transformOperationObj(
1010
globalParameters,
1111
immutableTypes,
1212
pathItem = {},
13+
document,
1314
version,
1415
}: {
1516
pathItem?: PathItemObject;
1617
globalParameters?: Record<string, ParameterObject>;
1718
immutableTypes: boolean;
19+
document: SourceDocument;
1820
version: number;
1921
}
2022
): string {
@@ -27,13 +29,15 @@ export function transformOperationObj(
2729
output += ` ${readonly}parameters: {\n ${transformParametersArray(parameters, {
2830
globalParameters,
2931
immutableTypes,
32+
document,
3033
version,
3134
})}\n }\n`;
3235
}
3336

3437
if (operation.responses) {
3538
output += ` ${readonly}responses: {\n ${transformResponsesObj(operation.responses, {
3639
immutableTypes,
40+
document,
3741
})}\n }\n`;
3842
}
3943

@@ -44,7 +48,7 @@ export function transformOperationObj(
4448
if (operation.requestBody.description) output += comment(operation.requestBody.description);
4549

4650
output += ` ${readonly}requestBody: {\n`; // open requestBody
47-
output += ` ${transformRequestBodyObj(operation.requestBody, { immutableTypes })}`;
51+
output += ` ${transformRequestBodyObj(operation.requestBody, { immutableTypes, document })}`;
4852
output += ` }\n`; // close requestBody
4953
}
5054
}
@@ -54,7 +58,7 @@ export function transformOperationObj(
5458

5559
export function transformRequestBodyObj(
5660
requestBody: RequestBody,
57-
{ immutableTypes }: { immutableTypes: boolean }
61+
{ immutableTypes, document }: { immutableTypes: boolean; document: SourceDocument }
5862
): string {
5963
const readonly = tsReadonly(immutableTypes);
6064

@@ -66,7 +70,7 @@ export function transformRequestBodyObj(
6670
output += ` ${readonly}content: {\n`; // open content
6771

6872
Object.entries(content).forEach(([k, v]) => {
69-
output += ` ${readonly}"${k}": ${transformSchemaObj(v.schema, { immutableTypes })};\n`;
73+
output += ` ${readonly}"${k}": ${transformSchemaObj(v.schema, { immutableTypes, document })};\n`;
7074
});
7175
output += ` }\n`; // close content
7276
} else {

src/transform/parameters.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { ParameterObject, ReferenceObject } from "../types";
2-
import { comment, tsReadonly } from "../utils";
1+
import { ParameterObject, ReferenceObject, SourceDocument } from "../types";
2+
import { comment, resolveRefIfNeeded, tsReadonly } from "../utils";
33
import { transformSchemaObj } from "./schema";
44

55
export function transformParametersArray(
66
parameters: (ReferenceObject | ParameterObject)[],
77
{
88
globalParameters,
99
immutableTypes,
10+
document,
1011
version,
1112
}: {
1213
globalParameters?: Record<string, ParameterObject>;
1314
immutableTypes: boolean;
15+
document: SourceDocument;
1416
version: number;
1517
}
1618
): string {
@@ -55,18 +57,26 @@ export function transformParametersArray(
5557
if (paramObj.description) paramComment += paramObj.description;
5658
if (paramComment) output += comment(paramComment);
5759

58-
const required = paramObj.required ? `` : `?`;
60+
let hasDefault = false;
61+
if (paramObj.schema) {
62+
const paramSchema = resolveRefIfNeeded(document, paramObj.schema);
63+
if (paramSchema != null && paramSchema.default) {
64+
hasDefault = true;
65+
}
66+
}
67+
68+
const required = paramObj.required || hasDefault ? `` : `?`;
5969
let paramType = ``;
6070
if (version === 2) {
6171
if (paramObj.in === "body" && paramObj.schema) {
62-
paramType = transformSchemaObj(paramObj.schema, { immutableTypes });
72+
paramType = transformSchemaObj(paramObj.schema, { immutableTypes, document });
6373
} else if (paramObj.type) {
64-
paramType = transformSchemaObj(paramObj, { immutableTypes });
74+
paramType = transformSchemaObj(paramObj, { immutableTypes, document });
6575
} else {
6676
paramType = "unknown";
6777
}
6878
} else if (version === 3) {
69-
paramType = paramObj.schema ? transformSchemaObj(paramObj.schema, { immutableTypes }) : "unknown";
79+
paramType = paramObj.schema ? transformSchemaObj(paramObj.schema, { immutableTypes, document }) : "unknown";
7080
}
7181
output += ` ${readonly}"${paramName}"${required}: ${paramType};\n`;
7282
});

src/transform/paths.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { OperationObject, ParameterObject, PathItemObject } from "../types";
1+
import { OperationObject, ParameterObject, PathItemObject, SourceDocument } from "../types";
22
import { comment, transformRef, tsReadonly } from "../utils";
33
import { transformOperationObj } from "./operation";
44
import { transformParametersArray } from "./parameters";
@@ -8,12 +8,13 @@ interface TransformPathsObjOption {
88
immutableTypes: boolean;
99
operations: Record<string, { operation: OperationObject; pathItem: PathItemObject }>;
1010
version: number;
11+
document: SourceDocument;
1112
}
1213

1314
/** Note: this needs to mutate objects passed in */
1415
export function transformPathsObj(
1516
paths: Record<string, PathItemObject>,
16-
{ globalParameters, immutableTypes, operations, version }: TransformPathsObjOption
17+
{ globalParameters, immutableTypes, operations, version, document }: TransformPathsObjOption
1718
): string {
1819
const readonly = tsReadonly(immutableTypes);
1920

@@ -49,6 +50,7 @@ export function transformPathsObj(
4950
immutableTypes,
5051
pathItem,
5152
version,
53+
document,
5254
})}\n }\n`;
5355
});
5456

@@ -57,6 +59,7 @@ export function transformPathsObj(
5759
output += ` ${readonly}parameters: {\n ${transformParametersArray(pathItem.parameters, {
5860
globalParameters,
5961
immutableTypes,
62+
document,
6063
version,
6164
})}\n }\n`;
6265
}

src/transform/responses.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { RequestBody, SchemaFormatter } from "../types";
1+
import { RequestBody, SchemaFormatter, SourceDocument } from "../types";
22
import { comment, transformRef, tsReadonly } from "../utils";
33
import { transformHeaderObjMap } from "./headers";
44
import { transformSchemaObj } from "./schema";
@@ -8,6 +8,7 @@ const resType = (res: string | number) => (res === 204 || (res >= 300 && res < 4
88

99
interface Options {
1010
formatter?: SchemaFormatter;
11+
document: SourceDocument;
1112
immutableTypes: boolean;
1213
}
1314

0 commit comments

Comments
 (0)