Skip to content

Commit 5a09a7a

Browse files
hedgepigdanielcyclops23Daniel Playfair Caljs2me
authored
Pass through required properties to allOf/anyOf/oneOf children (#342)
* Pass through required properties to allOf children * extend fix to anyOf and oneOf * fix: account for children making parent fields required Co-authored-by: Anders Cassidy <[email protected]> Co-authored-by: Daniel Playfair Cal <[email protected]> Co-authored-by: Sergey S. Volkov <[email protected]>
1 parent f6c9046 commit 5a09a7a

File tree

4 files changed

+108
-13
lines changed

4 files changed

+108
-13
lines changed

src/schema.js

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,16 +186,57 @@ const getObjectTypeContent = (schema) => {
186186
const complexTypeGetter = (schema) => getInlineParseContent(schema);
187187
const filterContents = (contents, types) => _.filter(contents, (type) => !_.includes(types, type));
188188

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

194235
return checkAndAddNull(schema, filterContents(combined, [TS_KEYWORDS.ANY]).join(" | "));
195236
},
196237
[SCHEMA_TYPES.COMPLEX_ALL_OF]: (schema) => {
197238
// T1 & T2
198-
const combined = _.map(schema.allOf, complexTypeGetter);
239+
const combined = _.map(schema.allOf.map(makeAddRequiredToChildSchema(schema)), complexTypeGetter);
199240
return checkAndAddNull(
200241
schema,
201242
filterContents(combined, [...JS_EMPTY_TYPES, ...JS_PRIMITIVE_TYPES, TS_KEYWORDS.ANY]).join(
@@ -205,7 +246,7 @@ const complexSchemaParsers = {
205246
},
206247
[SCHEMA_TYPES.COMPLEX_ANY_OF]: (schema) => {
207248
// T1 | T2 | (T1 & T2)
208-
const combined = _.map(schema.anyOf, complexTypeGetter);
249+
const combined = _.map(makeAddRequiredToChildSchema(schema), complexTypeGetter);
209250
const nonEmptyTypesCombined = filterContents(combined, [
210251
...JS_EMPTY_TYPES,
211252
...JS_PRIMITIVE_TYPES,

tests/generated/v3.0/allof-example.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export interface Pet {
1313
pet_type: string;
1414
}
1515

16-
export type Dog = Pet & { bark?: boolean; breed?: "Dingo" | "Husky" | "Retriever" | "Shepherd" };
16+
export type Dog = Pet & { bark?: boolean; breed: "Dingo" | "Husky" | "Retriever" | "Shepherd" };
1717

1818
export type Cat = Pet & { hunts?: boolean; age?: number };
1919

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

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10610,9 +10610,41 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1061010610
*/
1061110611
gistsUpdate: (
1061210612
gistId: string,
10613-
data: (any | any | null) & {
10613+
data: (
10614+
| { description: string }
10615+
| {
10616+
files: Record<
10617+
string,
10618+
(
10619+
| { content: string }
10620+
| { filename: string | null }
10621+
| object
10622+
| ({ content: string } & { filename: string | null } & object)
10623+
) & { content?: string; filename?: string | null }
10624+
>;
10625+
}
10626+
| ({ description: string } & {
10627+
files: Record<
10628+
string,
10629+
(
10630+
| { content: string }
10631+
| { filename: string | null }
10632+
| object
10633+
| ({ content: string } & { filename: string | null } & object)
10634+
) & { content?: string; filename?: string | null }
10635+
>;
10636+
})
10637+
) & {
1061410638
description?: string;
10615-
files?: Record<string, (any | any | object | null) & { content?: string; filename?: string | null }>;
10639+
files?: Record<
10640+
string,
10641+
(
10642+
| { content: string }
10643+
| { filename: string | null }
10644+
| object
10645+
| ({ content: string } & { filename: string | null } & object)
10646+
) & { content?: string; filename?: string | null }
10647+
>;
1061610648
},
1061710649
params: RequestParams = {},
1061810650
) =>
@@ -15917,9 +15949,21 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1591715949
owner: string,
1591815950
repo: string,
1591915951
data: (
15920-
| { status?: "completed"; [key: string]: any }
15921-
| { status?: "queued" | "in_progress"; [key: string]: any }
15922-
| ({ status?: "completed"; [key: string]: any } & { status?: "queued" | "in_progress"; [key: string]: any })
15952+
| {
15953+
status?: "completed";
15954+
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
15955+
name: string;
15956+
head_sha: string;
15957+
[key: string]: any;
15958+
}
15959+
| { status?: "queued" | "in_progress"; name: string; head_sha: string; [key: string]: any }
15960+
| ({
15961+
status?: "completed";
15962+
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
15963+
name: string;
15964+
head_sha: string;
15965+
[key: string]: any;
15966+
} & { status?: "queued" | "in_progress"; name: string; head_sha: string; [key: string]: any })
1592315967
) & {
1592415968
name: string;
1592515969
head_sha: string;
@@ -15988,9 +16032,17 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
1598816032
repo: string,
1598916033
checkRunId: number,
1599016034
data: (
15991-
| { status?: "completed"; [key: string]: any }
16035+
| {
16036+
status?: "completed";
16037+
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
16038+
[key: string]: any;
16039+
}
1599216040
| { status?: "queued" | "in_progress"; [key: string]: any }
15993-
| ({ status?: "completed"; [key: string]: any } & { status?: "queued" | "in_progress"; [key: string]: any })
16041+
| ({
16042+
status?: "completed";
16043+
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required";
16044+
[key: string]: any;
16045+
} & { status?: "queued" | "in_progress"; [key: string]: any })
1599416046
) & {
1599516047
name?: string;
1599616048
details_url?: string;

tests/schemas/v3.0/allof-example.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ components:
2929
discriminator:
3030
propertyName: pet_type
3131
Dog: # "Dog" is a value for the pet_type property (the discriminator value)
32-
allOf: # Combines the main `Pet` schema with `Dog`-specific properties
32+
required:
33+
- breed
34+
allOf: # Combines the main `Pet` schema with `Dog`-specific properties
3335
- $ref: '#/components/schemas/Pet'
3436
- type: object
3537
# all other properties specific to a `Dog`
@@ -48,4 +50,4 @@ components:
4850
hunts:
4951
type: boolean
5052
age:
51-
type: integer
53+
type: integer

0 commit comments

Comments
 (0)