Skip to content

Commit 5d8c187

Browse files
author
Daniel Playfair Cal
committed
fix: account for children making parent fields required
1 parent 3ff93cf commit 5d8c187

File tree

2 files changed

+105
-21
lines changed

2 files changed

+105
-21
lines changed

src/schema.js

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -178,22 +178,57 @@ const getObjectTypeContent = (schema) => {
178178
const complexTypeGetter = (schema) => getInlineParseContent(schema);
179179
const filterContents = (contents, types) => _.filter(contents, (type) => !_.includes(types, type));
180180

181+
const makeAddRequiredToChildSchema = (parentSchema) => (childSchema) => {
182+
let required = childSchema.required || [];
183+
let properties = childSchema.properties || {};
184+
185+
// Inherit all the required fields from the parent schema that are defined
186+
// either on the parent schema or on the child schema
187+
// TODO: any that are defined at grandparents or higher are ignored
188+
required = required.concat(
189+
(parentSchema.required || []).filter(
190+
(key) =>
191+
!required.includes(key) && (_.keys(properties).includes(key) || _.keys(parentSchema.properties).includes(key)),
192+
),
193+
);
194+
195+
// Identify properties that are required in the child schema, but
196+
// defined only in the parent schema (TODO: this only works one level deep)
197+
const parentPropertiesRequiredByChild = required.filter(
198+
(key) => !_.keys(childSchema.properties).includes(key) && _.keys(parentSchema.properties).includes(key),
199+
);
200+
201+
// Add such properties to the child so that they can be overriden and made required
202+
properties = {
203+
...properties,
204+
...parentPropertiesRequiredByChild.reduce(
205+
(additionalProperties, key) => ({
206+
...additionalProperties,
207+
[key]: (parentSchema.properties || {})[key],
208+
}),
209+
{},
210+
),
211+
};
212+
213+
return _.merge(
214+
{
215+
required: required,
216+
properties: properties,
217+
},
218+
childSchema,
219+
);
220+
};
221+
181222
const complexSchemaParsers = {
182223
[SCHEMA_TYPES.COMPLEX_ONE_OF]: (schema) => {
183224
// T1 | T2
184-
const combined = _.map(
185-
schema.oneOf.map((s) => _.merge({ required: schema.required }, s)),
186-
complexTypeGetter,
187-
);
225+
const combined = _.map(schema.oneOf.map(makeAddRequiredToChildSchema(schema)), complexTypeGetter);
188226

189227
return checkAndAddNull(schema, filterContents(combined, [TS_KEYWORDS.ANY]).join(" | "));
190228
},
191229
[SCHEMA_TYPES.COMPLEX_ALL_OF]: (schema) => {
192230
// T1 & T2
193-
const combined = _.map(
194-
schema.allOf.map((s) => _.merge({ required: schema.required }, s)),
195-
complexTypeGetter,
196-
);
231+
const combined = _.map(schema.allOf.map(makeAddRequiredToChildSchema(schema)), complexTypeGetter);
197232
return checkAndAddNull(
198233
schema,
199234
filterContents(combined, [...JS_EMPTY_TYPES, ...JS_PRIMITIVE_TYPES, TS_KEYWORDS.ANY]).join(
@@ -203,10 +238,7 @@ const complexSchemaParsers = {
203238
},
204239
[SCHEMA_TYPES.COMPLEX_ANY_OF]: (schema) => {
205240
// T1 | T2 | (T1 & T2)
206-
const combined = _.map(
207-
schema.anyOf.map((s) => _.merge({ required: schema.required }, s)),
208-
complexTypeGetter,
209-
);
241+
const combined = _.map(makeAddRequiredToChildSchema(schema), complexTypeGetter);
210242
const nonEmptyTypesCombined = filterContents(combined, [
211243
...JS_EMPTY_TYPES,
212244
...JS_PRIMITIVE_TYPES,

tests/generated/v3.0/full-swagger-scheme.ts

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10636,9 +10636,41 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1063610636
*/
1063710637
gistsUpdate: (
1063810638
gistId: string,
10639-
data: (any | any | null) & {
10639+
data: (
10640+
| { description: string }
10641+
| {
10642+
files: Record<
10643+
string,
10644+
(
10645+
| { content: string }
10646+
| { filename: string | null }
10647+
| object
10648+
| ({ content: string } & { filename: string | null } & object)
10649+
) & { content?: string; filename?: string | null }
10650+
>;
10651+
}
10652+
| ({ description: string } & {
10653+
files: Record<
10654+
string,
10655+
(
10656+
| { content: string }
10657+
| { filename: string | null }
10658+
| object
10659+
| ({ content: string } & { filename: string | null } & object)
10660+
) & { content?: string; filename?: string | null }
10661+
>;
10662+
})
10663+
) & {
1064010664
description?: string;
10641-
files?: Record<string, (any | any | object | null) & { content?: string; filename?: string | null }>;
10665+
files?: Record<
10666+
string,
10667+
(
10668+
| { content: string }
10669+
| { filename: string | null }
10670+
| object
10671+
| ({ content: string } & { filename: string | null } & object)
10672+
) & { content?: string; filename?: string | null }
10673+
>;
1064210674
},
1064310675
params: RequestParams = {},
1064410676
) =>
@@ -15943,17 +15975,29 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1594315975
owner: string,
1594415976
repo: string,
1594515977
data: (
15946-
| { status?: "completed"; [key: string]: any }
15947-
| { status?: "queued" | "in_progress"; [key: string]: any }
15948-
| ({ status?: "completed"; [key: string]: any } & { status?: "queued" | "in_progress"; [key: string]: any })
15978+
| {
15979+
status?: "completed";
15980+
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
15981+
name: string;
15982+
head_sha: string;
15983+
[key: string]: any;
15984+
}
15985+
| { status?: "queued" | "in_progress"; name: string; head_sha: string; [key: string]: any }
15986+
| ({
15987+
status?: "completed";
15988+
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
15989+
name: string;
15990+
head_sha: string;
15991+
[key: string]: any;
15992+
} & { status?: "queued" | "in_progress"; name: string; head_sha: string; [key: string]: any })
1594915993
) & {
15950-
name?: string;
15994+
name: string;
1595115995
head_sha: string;
1595215996
details_url?: string;
1595315997
external_id?: string;
1595415998
status?: "queued" | "in_progress" | "completed";
1595515999
started_at?: string;
15956-
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
16000+
conclusion?: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
1595716001
completed_at?: string;
1595816002
output?: {
1595916003
title: string;
@@ -16014,9 +16058,17 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1601416058
repo: string,
1601516059
checkRunId: number,
1601616060
data: (
16017-
| { status?: "completed"; [key: string]: any }
16061+
| {
16062+
status?: "completed";
16063+
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
16064+
[key: string]: any;
16065+
}
1601816066
| { status?: "queued" | "in_progress"; [key: string]: any }
16019-
| ({ status?: "completed"; [key: string]: any } & { status?: "queued" | "in_progress"; [key: string]: any })
16067+
| ({
16068+
status?: "completed";
16069+
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
16070+
[key: string]: any;
16071+
} & { status?: "queued" | "in_progress"; [key: string]: any })
1602016072
) & {
1602116073
name?: string;
1602216074
details_url?: string;

0 commit comments

Comments
 (0)