Skip to content

Commit 15e22f6

Browse files
Alan-ChaErikWittern
authored andcommitted
Collapse required schema properties
Signed-off-by: Alan Cha <[email protected]>
1 parent dd98687 commit 15e22f6

File tree

10 files changed

+130
-32
lines changed

10 files changed

+130
-32
lines changed

packages/openapi-to-graphql/lib/preprocessor.js

Lines changed: 17 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-to-graphql/lib/preprocessor.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-to-graphql/lib/schema_builder.js

Lines changed: 8 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-to-graphql/lib/schema_builder.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-to-graphql/lib/types/operation.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ import * as GraphQLJSON from 'graphql-type-json';
88
export declare type DataDefinition = {
99
preferredName: string;
1010
schema: SchemaObject;
11+
/**
12+
* Similar to the required property in object schemas but because of certain
13+
* keywords to combine schemas, e.g. "allOf", this resolves the required
14+
* property in all subschemas
15+
*/
16+
required: string[];
1117
targetGraphQLType: string;
1218
links: {
1319
[key: string]: LinkObject;

packages/openapi-to-graphql/src/preprocessor.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ export function createDataDef(
544544
* currently, it does not.
545545
*/
546546
schema,
547+
required: [],
547548
targetGraphQLType,
548549
subDefinitions: undefined,
549550
links: saneLinks,
@@ -583,7 +584,14 @@ export function createDataDef(
583584

584585
// Resolve allOf element in schema if applicable
585586
if ('allOf' in schema) {
586-
addAllOfToDataDef(def, schema, isInputObjectType, data, oas)
587+
addAllOfToDataDef(
588+
def,
589+
schema,
590+
def.required,
591+
isInputObjectType,
592+
data,
593+
oas
594+
)
587595
} else if ('anyOf' in schema) {
588596
handleWarning({
589597
typeKey: 'UNSUPPORTED_JSON_SCHEMA_KEYWORD',
@@ -614,7 +622,14 @@ export function createDataDef(
614622
}
615623

616624
// Add existing properties (regular object type)
617-
addObjectPropertiesToDataDef(def, schema, isInputObjectType, data, oas)
625+
addObjectPropertiesToDataDef(
626+
def,
627+
schema,
628+
def.required,
629+
isInputObjectType,
630+
data,
631+
oas
632+
)
618633
} else if (targetGraphQLType === 'union') {
619634
def.subDefinitions = []
620635

@@ -822,6 +837,7 @@ function getSchemaName(
822837
function addAllOfToDataDef(
823838
def: DataDefinition,
824839
schema: SchemaObject,
840+
required: string[],
825841
isInputObjectType: boolean,
826842
data: PreprocessingData,
827843
oas?: Oas3
@@ -834,11 +850,18 @@ function addAllOfToDataDef(
834850

835851
// Recurse into nested allOf (if applicable)
836852
if ('allOf' in subSchema) {
837-
addAllOfToDataDef(def, subSchema, isInputObjectType, data, oas)
853+
addAllOfToDataDef(def, subSchema, required, isInputObjectType, data, oas)
838854
}
839855

840856
// Add properties of the subSchema
841-
addObjectPropertiesToDataDef(def, subSchema, isInputObjectType, data, oas)
857+
addObjectPropertiesToDataDef(
858+
def,
859+
subSchema,
860+
required,
861+
isInputObjectType,
862+
data,
863+
oas
864+
)
842865
})
843866
}
844867

@@ -848,10 +871,22 @@ function addAllOfToDataDef(
848871
function addObjectPropertiesToDataDef(
849872
def: DataDefinition,
850873
schema: SchemaObject,
874+
required: string[],
851875
isInputObjectType: boolean,
852876
data: PreprocessingData,
853877
oas?: Oas3
854878
) {
879+
/**
880+
* Resolve all required properties
881+
*
882+
* TODO: required may contain duplicates, which is not necessarily a problem
883+
*/
884+
if (Array.isArray(schema.required)) {
885+
schema.required.forEach(requiredProperty => {
886+
required.push(requiredProperty)
887+
})
888+
}
889+
855890
for (let propertyKey in schema.properties) {
856891
let propSchemaName = propertyKey
857892
let propSchema = schema.properties[propertyKey]

packages/openapi-to-graphql/src/schema_builder.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ function createFields({
612612
})
613613

614614
const requiredProperty =
615-
'required' in def.schema && def.schema.required.includes(fieldTypeKey) // The full schema, not field schema, will contain the required property
615+
typeof def.required === 'object' && def.required.includes(fieldTypeKey)
616616

617617
// Finally, add the object type to the fields (using sanitized field name)
618618
if (objectType) {
@@ -1217,20 +1217,19 @@ export function getArgs({
12171217
})
12181218

12191219
// Sanitize the argument name
1220-
const saneName = data.options.genericPayloadArgName
1221-
? 'requestBody'
1222-
: Oas3Tools.sanitize(
1220+
const saneName = data.options.genericPayloadArgName ?
1221+
'requestBody' :
1222+
Oas3Tools.sanitize(
12231223
requestPayloadDef.graphQLInputObjectTypeName,
12241224
Oas3Tools.CaseStyle.camelCase
12251225
)
12261226

1227-
let reqRequired = false
1228-
if (
1227+
const reqRequired =
12291228
typeof operation === 'object' &&
12301229
typeof operation.payloadRequired === 'boolean'
1231-
) {
1232-
reqRequired = operation.payloadRequired
1233-
}
1230+
? operation.payloadRequired
1231+
: false
1232+
12341233
args[saneName] = {
12351234
type: reqRequired ? new GraphQLNonNull(reqObjectType) : reqObjectType,
12361235
// TODO: addendum to the description explaining this is the request body

packages/openapi-to-graphql/src/types/operation.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ export type DataDefinition = {
3636
// The schema of the data type, why may have gone through some resolution, and is used with preferredName to identify a specific GraphQL type
3737
schema: SchemaObject
3838

39+
/**
40+
* Similar to the required property in object schemas but because of certain
41+
* keywords to combine schemas, e.g. "allOf", this resolves the required
42+
* property in all subschemas
43+
*/
44+
required: string[]
45+
3946
// The type GraphQL type this dataDefintion will be created into
4047
targetGraphQLType: string
4148

packages/openapi-to-graphql/test/example_api.test.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2258,4 +2258,44 @@ test('Option genericPayloadArgName', () => {
22582258
})
22592259

22602260
return Promise.all([promise, promise2])
2261-
})
2261+
})
2262+
2263+
test('Non-nullable properties from nested allOf', () => {
2264+
// Check query/mutation field descriptions
2265+
const query = `{
2266+
__type(name: "Nomenclature") {
2267+
fields {
2268+
name
2269+
type {
2270+
kind
2271+
ofType {
2272+
name
2273+
kind
2274+
}
2275+
}
2276+
}
2277+
}
2278+
}`
2279+
2280+
return openAPIToGraphQL.createGraphQlSchema(oas).then(({ schema }) => {
2281+
const ast = parse(query)
2282+
const errors = validate(schema, ast)
2283+
expect(errors).toEqual([])
2284+
return graphql(schema, query).then(result => {
2285+
expect(
2286+
result.data['__type'].fields.find(field => {
2287+
return field.name === 'family'
2288+
})
2289+
).toEqual({
2290+
name: 'family',
2291+
type: {
2292+
kind: 'NON_NULL',
2293+
ofType: {
2294+
name: 'String',
2295+
kind: 'SCALAR'
2296+
}
2297+
}
2298+
})
2299+
})
2300+
})
2301+
})

packages/openapi-to-graphql/test/fixtures/example_oas.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,8 @@
12431243
"family": {
12441244
"$ref": "#/components/schemas/familyString"
12451245
}
1246-
}
1246+
},
1247+
"required": ["family"]
12471248
},
12481249
{
12491250
"properties": {

0 commit comments

Comments
 (0)