Skip to content

Commit 3292d31

Browse files
committed
Fix required attribute by considering schemas.
Resolves openapi-ts#584
1 parent 787eb1e commit 3292d31

17 files changed

+891
-775
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; version: number }
7+
options: { formatter?: SchemaFormatter; immutableTypes: boolean; version: number, 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
@@ -29,6 +29,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
2929
immutableTypes,
3030
required: Object.keys(schema),
3131
version,
32+
document: schema,
3233
})}\n}`;
3334
}
3435
case 3: {
@@ -37,6 +38,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
3738
immutableTypes,
3839
required: Object.keys(schema),
3940
version,
41+
document: schema,
4042
})}\n }\n\n`;
4143
}
4244
}
@@ -49,6 +51,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
4951
globalParameters: (schema.components && schema.components.parameters) || schema.parameters,
5052
immutableTypes,
5153
operations,
54+
document: schema,
5255
version,
5356
});
5457
}
@@ -63,6 +66,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
6366
immutableTypes,
6467
required: Object.keys(schema.definitions),
6568
version,
69+
document: schema,
6670
})}\n}\n\n`;
6771
}
6872

@@ -74,6 +78,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
7478
immutableTypes,
7579
required,
7680
version,
81+
document: schema,
7782
})}\n }\n\n`;
7883
}
7984

@@ -83,6 +88,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
8388
formatter,
8489
immutableTypes,
8590
version,
91+
document: schema,
8692
})}\n }\n\n`;
8793
}
8894
break;
@@ -100,6 +106,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
100106
immutableTypes,
101107
required,
102108
version,
109+
document: schema,
103110
})}\n }\n`;
104111
}
105112

@@ -109,6 +116,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
109116
formatter,
110117
immutableTypes,
111118
version,
119+
document: schema,
112120
})}\n }\n`;
113121
}
114122

@@ -120,6 +128,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
120128
immutableTypes,
121129
required,
122130
version,
131+
document: schema,
123132
})}\n }\n`;
124133
}
125134

@@ -129,13 +138,15 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
129138
formatter,
130139
immutableTypes,
131140
version,
141+
document: schema,
132142
})}\n }\n`;
133143
}
134144

135145
// #/components/headers
136146
if (schema.components.headers) {
137147
output += ` ${readonly}headers: {\n ${transformHeaderObjMap(schema.components.headers, {
138148
formatter,
149+
document: schema,
139150
immutableTypes,
140151
version,
141152
})} }\n`;
@@ -155,6 +166,7 @@ export function transformAll(schema: any, { formatter, immutableTypes, rawSchema
155166
pathItem,
156167
globalParameters: (schema.components && schema.components.parameters) || schema.parameters,
157168
immutableTypes,
169+
document: schema,
158170
version,
159171
})}\n }\n`;
160172
});

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,6 +29,7 @@ export function transformOperationObj(
2729
output += ` ${readonly}parameters: {\n ${transformParametersArray(parameters, {
2830
globalParameters,
2931
immutableTypes,
32+
document,
3033
version,
3134
})}\n }\n`;
3235
}
@@ -35,6 +38,7 @@ export function transformOperationObj(
3538
output += ` ${readonly}responses: {\n ${transformResponsesObj(operation.responses, {
3639
immutableTypes,
3740
version,
41+
document,
3842
})}\n }\n`;
3943
}
4044

@@ -45,7 +49,7 @@ export function transformOperationObj(
4549
if (operation.requestBody.description) output += comment(operation.requestBody.description);
4650

4751
output += ` ${readonly}requestBody: {\n`; // open requestBody
48-
output += ` ${transformRequestBodyObj(operation.requestBody, { immutableTypes, version })}`;
52+
output += ` ${transformRequestBodyObj(operation.requestBody, { immutableTypes, version, document })}`;
4953
output += ` }\n`; // close requestBody
5054
}
5155
}
@@ -55,7 +59,7 @@ export function transformOperationObj(
5559

5660
export function transformRequestBodyObj(
5761
requestBody: RequestBody,
58-
{ immutableTypes, version }: { immutableTypes: boolean; version: number }
62+
{ immutableTypes, version, document }: { immutableTypes: boolean; version: number; document: SourceDocument }
5963
): string {
6064
const readonly = tsReadonly(immutableTypes);
6165

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

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

src/transform/parameters.ts

+26-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 {
@@ -34,6 +36,8 @@ export function transformParametersArray(
3436
} else if (version === 3) {
3537
mappedParams[reference.in][reference.name || paramName] = {
3638
...reference,
39+
// They want to keep this ref here so it references
40+
// the components, but it does violate the standards.
3741
schema: { $ref: paramObj.$ref },
3842
};
3943
}
@@ -55,20 +59,36 @@ export function transformParametersArray(
5559
if (paramObj.description) paramComment += paramObj.description;
5660
if (paramComment) output += comment(paramComment);
5761

58-
const required = paramObj.required ? `` : `?`;
62+
let hasDefault = false;
63+
if (paramObj.schema) {
64+
const actualParam = resolveRefIfNeeded<ParameterObject>(document, paramObj.schema as ReferenceObject);
65+
66+
// Because the schema refs have been re-written to reference the global parameters
67+
// need to look a little deeper to get the real schema.
68+
if (actualParam != null && actualParam.schema != null) {
69+
const actualParamSchema = resolveRefIfNeeded(document, actualParam?.schema);
70+
71+
if (actualParamSchema != null && actualParamSchema.default != null) {
72+
hasDefault = true;
73+
}
74+
}
75+
}
76+
77+
const required = (paramObj.required || hasDefault) ? `` : `?`;
5978
let paramType = ``;
6079
if (version === 2) {
6180
if (paramObj.in === "body" && paramObj.schema) {
62-
paramType = transformSchemaObj(paramObj.schema, { immutableTypes, version });
81+
paramType = transformSchemaObj(paramObj.schema, { immutableTypes, version, document });
6382
} else if (paramObj.type) {
64-
paramType = transformSchemaObj(paramObj, { immutableTypes, version });
83+
paramType = transformSchemaObj(paramObj, { immutableTypes, version, document });
6584
} else {
6685
paramType = "unknown";
6786
}
6887
} else if (version === 3) {
69-
paramType = paramObj.schema ? transformSchemaObj(paramObj.schema, { immutableTypes, version }) : "unknown";
88+
paramType = paramObj.schema ? transformSchemaObj(paramObj.schema, { immutableTypes, version, document }) : "unknown";
7089
}
7190
output += ` ${readonly}"${paramName}"${required}: ${paramType};\n`;
91+
7292
});
7393
output += ` }\n`; // close in
7494
});

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
version: number;
1314
}

0 commit comments

Comments
 (0)