Skip to content

Commit d1e793f

Browse files
committed
Go
1 parent 546cc10 commit d1e793f

File tree

8 files changed

+163
-101
lines changed

8 files changed

+163
-101
lines changed

packages/loaders/json-schema/src/directives.ts

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,20 @@ export const DiscriminatorDirective = new GraphQLDirective({
8787
field: {
8888
type: GraphQLString,
8989
},
90-
},
91-
});
92-
93-
export const DiscriminatorMappingDirective = new GraphQLDirective({
94-
name: 'discriminatorMapping',
95-
locations: [DirectiveLocation.INTERFACE, DirectiveLocation.UNION],
96-
args: {
97-
value: {
98-
type: GraphQLString,
99-
},
100-
schema: {
101-
type: GraphQLString,
90+
mapping: {
91+
type: ObjMapScalar,
10292
},
10393
},
10494
});
10595

106-
export function processDiscriminatorAnnotations(
107-
interfaceType: GraphQLInterfaceType,
108-
fieldName: string,
109-
) {
110-
interfaceType.resolveType = root => root[fieldName];
96+
export function processDiscriminatorAnnotations({
97+
interfaceType,
98+
discriminatorFieldName,
99+
}: {
100+
interfaceType: GraphQLInterfaceType;
101+
discriminatorFieldName: string;
102+
}) {
103+
interfaceType.resolveType = root => root[discriminatorFieldName];
111104
}
112105

113106
export const ResolveRootDirective = new GraphQLDirective({
@@ -570,7 +563,10 @@ export function processDirectives({
570563
for (const directiveAnnotation of directiveAnnotations) {
571564
switch (directiveAnnotation.name) {
572565
case 'discriminator':
573-
processDiscriminatorAnnotations(type, directiveAnnotation.args.field);
566+
processDiscriminatorAnnotations({
567+
interfaceType: type,
568+
discriminatorFieldName: directiveAnnotation.args.field,
569+
});
574570
break;
575571
}
576572
}
@@ -579,6 +575,7 @@ export function processDirectives({
579575
const directiveAnnotations = getDirectives(schema, type);
580576
let statusCodeTypeNameIndexMap: Record<number, string>;
581577
let discriminatorField: string;
578+
let discriminatorMapping: Record<string, string>;
582579
for (const directiveAnnotation of directiveAnnotations) {
583580
switch (directiveAnnotation.name) {
584581
case 'statusCodeTypeName':
@@ -588,14 +585,16 @@ export function processDirectives({
588585
break;
589586
case 'discriminator':
590587
discriminatorField = directiveAnnotation.args.field;
588+
discriminatorMapping = directiveAnnotation.args.mapping;
591589
break;
592590
}
593591
}
594-
type.resolveType = getTypeResolverFromOutputTCs(
595-
type.getTypes(),
592+
type.resolveType = getTypeResolverFromOutputTCs({
593+
possibleTypes: type.getTypes(),
596594
discriminatorField,
597-
statusCodeTypeNameIndexMap,
598-
);
595+
discriminatorMapping,
596+
statusCodeTypeNameMap: statusCodeTypeNameIndexMap,
597+
});
599598
}
600599
if (isEnumType(type)) {
601600
const directiveAnnotations = getDirectives(schema, type);

packages/loaders/json-schema/src/getComposerFromJSONSchema.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ import { sanitizeNameForGraphQL } from '@graphql-mesh/utils';
5454
import {
5555
DictionaryDirective,
5656
DiscriminatorDirective,
57-
DiscriminatorMappingDirective,
5857
EnumDirective,
5958
ExampleDirective,
6059
LengthDirective,
@@ -738,26 +737,19 @@ export function getComposerFromJSONSchema(
738737
}
739738
if (subSchema.discriminator?.propertyName) {
740739
schemaComposer.addDirective(DiscriminatorDirective);
740+
const mappingByName: Record<string, string> = {};
741+
for (const discriminatorValue in subSchema.discriminator.mapping) {
742+
const ref = subSchema.discriminator.mapping[discriminatorValue];
743+
const typeName = ref.replace('#/components/schemas/', '');
744+
mappingByName[discriminatorValue] = typeName;
745+
}
741746
directives.push({
742747
name: 'discriminator',
743748
args: {
744749
field: subSchema.discriminator.propertyName,
750+
mapping: mappingByName,
745751
},
746752
});
747-
748-
if (subSchema.discriminator.mapping) {
749-
schemaComposer.addDirective(DiscriminatorMappingDirective);
750-
Object.keys(subSchema.discriminator.mapping).forEach(value => {
751-
const mappedSchema = subSchema.discriminator.mapping[value].split('schemas/')[1];
752-
directives.push({
753-
name: 'discriminatorMapping',
754-
args: {
755-
value,
756-
schema: mappedSchema,
757-
},
758-
});
759-
});
760-
}
761753
}
762754
const output = schemaComposer.createUnionTC({
763755
name: getValidTypeName({

packages/loaders/json-schema/src/getTypeResolverFromOutputTCs.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import { GraphQLObjectType, GraphQLTypeResolver } from 'graphql';
22
import { createGraphQLError } from '@graphql-tools/utils';
33

4-
export function getTypeResolverFromOutputTCs(
5-
possibleTypes: readonly GraphQLObjectType[],
6-
discriminatorField?: string,
7-
discriminatorMapping?: Record<string, string>,
8-
statusCodeTypeNameMap?: Record<string, string>,
9-
): GraphQLTypeResolver<any, any> {
4+
export function getTypeResolverFromOutputTCs({
5+
possibleTypes,
6+
discriminatorField,
7+
discriminatorMapping,
8+
statusCodeTypeNameMap,
9+
}: {
10+
possibleTypes: readonly GraphQLObjectType[];
11+
discriminatorField?: string;
12+
discriminatorMapping?: Record<string, string>;
13+
statusCodeTypeNameMap?: Record<string, string>;
14+
}): GraphQLTypeResolver<any, any> {
1015
return function resolveType(data: any) {
1116
if (data.__typename) {
1217
return data.__typename;
1318
} else if (discriminatorField != null && data[discriminatorField]) {
14-
return discriminatorMapping[data[discriminatorField]] || data[discriminatorField];
19+
const discriminatorValue = data[discriminatorField];
20+
return discriminatorMapping?.[discriminatorValue] || discriminatorValue;
1521
}
1622
if (data.$statusCode && statusCodeTypeNameMap) {
1723
const typeName =

packages/loaders/openapi/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
},
4545
"devDependencies": {
4646
"@graphql-tools/utils": "9.2.1",
47+
"@whatwg-node/fetch": "0.8.4",
4748
"@whatwg-node/router": "0.3.0",
4849
"graphql-yoga": "3.8.0",
4950
"json-bigint-patch": "0.0.8"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Discriminator Mapping should generate correct schema: discriminator-mapping 1`] = `
4+
"schema {
5+
query: Query
6+
}
7+
8+
directive @oneOf on OBJECT | INTERFACE
9+
10+
directive @discriminator(field: String, mapping: ObjMap) on INTERFACE | UNION
11+
12+
directive @globalOptions(sourceName: String, endpoint: String, operationHeaders: ObjMap, queryStringOptions: ObjMap, queryParams: ObjMap) on OBJECT
13+
14+
directive @httpOperation(path: String, operationSpecificHeaders: ObjMap, httpMethod: HTTPMethod, isBinary: Boolean, requestBaseBody: ObjMap, queryParamArgMap: ObjMap, queryStringOptionsByParam: ObjMap) on FIELD_DEFINITION
15+
16+
type Query @globalOptions(sourceName: "test") {
17+
pets_by_id(id: String!): Pet @httpOperation(path: "/pets/{args.id}", operationSpecificHeaders: "{\\"accept\\":\\"application/json\\"}", httpMethod: GET)
18+
}
19+
20+
union Pet @discriminator(field: "petType", mapping: "{\\"Dog\\":\\"DogDifferent\\",\\"Cat\\":\\"Cat\\"}") = Cat | DogDifferent
21+
22+
type Cat {
23+
petType: String
24+
cat_exclusive: String
25+
}
26+
27+
type DogDifferent {
28+
petType: String
29+
dog_exclusive: String
30+
}
31+
32+
scalar ObjMap
33+
34+
enum HTTPMethod {
35+
GET
36+
HEAD
37+
POST
38+
PUT
39+
DELETE
40+
CONNECT
41+
OPTIONS
42+
TRACE
43+
PATCH
44+
}"
45+
`;

packages/loaders/openapi/tests/__snapshots__/schemas.test.ts.snap

Lines changed: 6 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -41929,52 +41929,6 @@ enum HTTPMethod {
4192941929
}"
4193041930
`;
4193141931

41932-
exports[`Schemas DiscriminatorMapping should generate the correct schema: DiscriminatorMapping 1`] = `
41933-
"schema {
41934-
query: Query
41935-
}
41936-
41937-
directive @oneOf on OBJECT | INTERFACE
41938-
41939-
directive @discriminator(field: String) on INTERFACE | UNION
41940-
41941-
directive @discriminatorMapping(value: String, schema: String) on INTERFACE | UNION
41942-
41943-
directive @globalOptions(sourceName: String, endpoint: String, operationHeaders: ObjMap, queryStringOptions: ObjMap, queryParams: ObjMap) on OBJECT
41944-
41945-
directive @httpOperation(path: String, operationSpecificHeaders: ObjMap, httpMethod: HTTPMethod, isBinary: Boolean, requestBaseBody: ObjMap, queryParamArgMap: ObjMap, queryStringOptionsByParam: ObjMap) on FIELD_DEFINITION
41946-
41947-
type Query @globalOptions(sourceName: "DiscriminatorMapping") {
41948-
pets_by_id(id: String!): Pet @httpOperation(path: "/pets/{args.id}", operationSpecificHeaders: "{\\"accept\\":\\"application/json\\"}", httpMethod: GET)
41949-
}
41950-
41951-
union Pet @discriminator(field: "petType") @discriminatorMapping(value: "Dog", schema: "DogDifferent") @discriminatorMapping(value: "Cat", schema: "Cat") = Cat | DogDifferent
41952-
41953-
type Cat {
41954-
petType: String
41955-
cat_exclusive: String
41956-
}
41957-
41958-
type DogDifferent {
41959-
petType: String
41960-
dog_exclusive: String
41961-
}
41962-
41963-
scalar ObjMap
41964-
41965-
enum HTTPMethod {
41966-
GET
41967-
HEAD
41968-
POST
41969-
PUT
41970-
DELETE
41971-
CONNECT
41972-
OPTIONS
41973-
TRACE
41974-
PATCH
41975-
}"
41976-
`;
41977-
4197841932
exports[`Schemas GitHub should generate the correct schema: GitHub 1`] = `
4197941933
"schema {
4198041934
query: Query
@@ -49695,9 +49649,7 @@ directive @example(value: ObjMap) repeatable on FIELD_DEFINITION | OBJECT | INPU
4969549649

4969649650
directive @oneOf on OBJECT | INTERFACE
4969749651

49698-
directive @discriminator(field: String) on INTERFACE | UNION
49699-
49700-
directive @discriminatorMapping(value: String, schema: String) on INTERFACE | UNION
49652+
directive @discriminator(field: String, mapping: ObjMap) on INTERFACE | UNION
4970149653

4970249654
directive @globalOptions(sourceName: String, endpoint: String, operationHeaders: ObjMap, queryStringOptions: ObjMap, queryParams: ObjMap) on OBJECT
4970349655

@@ -49740,7 +49692,7 @@ type TicketMessageGet {
4974049692
Author: PersonGet @link(defaultRootType: "Mutation", defaultField: "TicketMessagesUpdateTicketMessage")
4974149693
}
4974249694

49743-
union PersonGet @discriminator(field: "_resolveType") @discriminatorMapping(value: "user", schema: "UserGet") @discriminatorMapping(value: "company", schema: "CompanyGet") = CompanyGet | UserGet
49695+
union PersonGet @discriminator(field: "_resolveType", mapping: "{\\"user\\":\\"UserGet\\",\\"company\\":\\"CompanyGet\\"}") = CompanyGet | UserGet
4974449696

4974549697
type CompanyGet {
4974649698
_resolveType: company_const!
@@ -50388,9 +50340,7 @@ directive @resolveRoot on FIELD_DEFINITION
5038850340

5038950341
directive @example(value: ObjMap) repeatable on FIELD_DEFINITION | OBJECT | INPUT_OBJECT | ENUM | SCALAR
5039050342

50391-
directive @discriminator(field: String) on INTERFACE | UNION
50392-
50393-
directive @discriminatorMapping(value: String, schema: String) on INTERFACE | UNION
50343+
directive @discriminator(field: String, mapping: ObjMap) on INTERFACE | UNION
5039450344

5039550345
directive @dictionary on FIELD_DEFINITION
5039650346

@@ -53410,7 +53360,7 @@ type PageBeanCustomFieldContextDefaultValue {
5341053360
values: [CustomFieldContextDefaultValue]
5341153361
}
5341253362

53413-
union CustomFieldContextDefaultValue @discriminator(field: "type") @discriminatorMapping(value: "option.cascading", schema: "CustomFieldContextDefaultValueCascadingOption") @discriminatorMapping(value: "option.multiple", schema: "CustomFieldContextDefaultValueMultipleOption") @discriminatorMapping(value: "option.single", schema: "CustomFieldContextDefaultValueSingleOption") @discriminatorMapping(value: "single.user.select", schema: "CustomFieldContextSingleUserPickerDefaults") @discriminatorMapping(value: "multi.user.select", schema: "CustomFieldContextDefaultValueMultiUserPicker") @discriminatorMapping(value: "grouppicker.single", schema: "CustomFieldContextDefaultValueSingleGroupPicker") @discriminatorMapping(value: "grouppicker.multiple", schema: "CustomFieldContextDefaultValueMultipleGroupPicker") @discriminatorMapping(value: "datepicker", schema: "CustomFieldContextDefaultValueDate") @discriminatorMapping(value: "datetimepicker", schema: "CustomFieldContextDefaultValueDateTime") @discriminatorMapping(value: "url", schema: "CustomFieldContextDefaultValueURL") @discriminatorMapping(value: "project", schema: "CustomFieldContextDefaultValueProject") @discriminatorMapping(value: "float", schema: "CustomFieldContextDefaultValueFloat") @discriminatorMapping(value: "labels", schema: "CustomFieldContextDefaultValueLabels") @discriminatorMapping(value: "textfield", schema: "CustomFieldContextDefaultValueTextField") @discriminatorMapping(value: "textarea", schema: "CustomFieldContextDefaultValueTextArea") @discriminatorMapping(value: "readonly", schema: "CustomFieldContextDefaultValueReadOnly") @discriminatorMapping(value: "version.single", schema: "CustomFieldContextDefaultValueSingleVersionPicker") @discriminatorMapping(value: "version.multiple", schema: "CustomFieldContextDefaultValueMultipleVersionPicker") @discriminatorMapping(value: "forge.string", schema: "CustomFieldContextDefaultValueForgeStringField") @discriminatorMapping(value: "forge.string.list", schema: "CustomFieldContextDefaultValueForgeMultiStringField") @discriminatorMapping(value: "forge.object", schema: "CustomFieldContextDefaultValueForgeObjectField") @discriminatorMapping(value: "forge.datetime", schema: "CustomFieldContextDefaultValueForgeDateTimeField") @discriminatorMapping(value: "forge.group", schema: "CustomFieldContextDefaultValueForgeGroupField") @discriminatorMapping(value: "forge.group.list", schema: "CustomFieldContextDefaultValueForgeMultiGroupField") @discriminatorMapping(value: "forge.number", schema: "CustomFieldContextDefaultValueForgeNumberField") @discriminatorMapping(value: "forge.user", schema: "CustomFieldContextDefaultValueForgeUserField") @discriminatorMapping(value: "forge.user.list", schema: "CustomFieldContextDefaultValueForgeMultiUserField") = CustomFieldContextDefaultValueCascadingOption | CustomFieldContextDefaultValueMultipleOption | CustomFieldContextDefaultValueSingleOption | CustomFieldContextSingleUserPickerDefaults | CustomFieldContextDefaultValueMultiUserPicker | CustomFieldContextDefaultValueSingleGroupPicker | CustomFieldContextDefaultValueMultipleGroupPicker | CustomFieldContextDefaultValueDate | CustomFieldContextDefaultValueDateTime | CustomFieldContextDefaultValueURL | CustomFieldContextDefaultValueProject | CustomFieldContextDefaultValueFloat | CustomFieldContextDefaultValueLabels | CustomFieldContextDefaultValueTextField | CustomFieldContextDefaultValueTextArea | CustomFieldContextDefaultValueReadOnly | CustomFieldContextDefaultValueSingleVersionPicker | CustomFieldContextDefaultValueMultipleVersionPicker | CustomFieldContextDefaultValueForgeStringField | CustomFieldContextDefaultValueForgeMultiStringField | CustomFieldContextDefaultValueForgeObjectField | CustomFieldContextDefaultValueForgeDateTimeField | CustomFieldContextDefaultValueForgeGroupField | CustomFieldContextDefaultValueForgeMultiGroupField | CustomFieldContextDefaultValueForgeNumberField | CustomFieldContextDefaultValueForgeUserField | CustomFieldContextDefaultValueForgeMultiUserField
53363+
union CustomFieldContextDefaultValue @discriminator(field: "type", mapping: "{\\"option.cascading\\":\\"CustomFieldContextDefaultValueCascadingOption\\",\\"option.multiple\\":\\"CustomFieldContextDefaultValueMultipleOption\\",\\"option.single\\":\\"CustomFieldContextDefaultValueSingleOption\\",\\"single.user.select\\":\\"CustomFieldContextSingleUserPickerDefaults\\",\\"multi.user.select\\":\\"CustomFieldContextDefaultValueMultiUserPicker\\",\\"grouppicker.single\\":\\"CustomFieldContextDefaultValueSingleGroupPicker\\",\\"grouppicker.multiple\\":\\"CustomFieldContextDefaultValueMultipleGroupPicker\\",\\"datepicker\\":\\"CustomFieldContextDefaultValueDate\\",\\"datetimepicker\\":\\"CustomFieldContextDefaultValueDateTime\\",\\"url\\":\\"CustomFieldContextDefaultValueURL\\",\\"project\\":\\"CustomFieldContextDefaultValueProject\\",\\"float\\":\\"CustomFieldContextDefaultValueFloat\\",\\"labels\\":\\"CustomFieldContextDefaultValueLabels\\",\\"textfield\\":\\"CustomFieldContextDefaultValueTextField\\",\\"textarea\\":\\"CustomFieldContextDefaultValueTextArea\\",\\"readonly\\":\\"CustomFieldContextDefaultValueReadOnly\\",\\"version.single\\":\\"CustomFieldContextDefaultValueSingleVersionPicker\\",\\"version.multiple\\":\\"CustomFieldContextDefaultValueMultipleVersionPicker\\",\\"forge.string\\":\\"CustomFieldContextDefaultValueForgeStringField\\",\\"forge.string.list\\":\\"CustomFieldContextDefaultValueForgeMultiStringField\\",\\"forge.object\\":\\"CustomFieldContextDefaultValueForgeObjectField\\",\\"forge.datetime\\":\\"CustomFieldContextDefaultValueForgeDateTimeField\\",\\"forge.group\\":\\"CustomFieldContextDefaultValueForgeGroupField\\",\\"forge.group.list\\":\\"CustomFieldContextDefaultValueForgeMultiGroupField\\",\\"forge.number\\":\\"CustomFieldContextDefaultValueForgeNumberField\\",\\"forge.user\\":\\"CustomFieldContextDefaultValueForgeUserField\\",\\"forge.user.list\\":\\"CustomFieldContextDefaultValueForgeMultiUserField\\"}") = CustomFieldContextDefaultValueCascadingOption | CustomFieldContextDefaultValueMultipleOption | CustomFieldContextDefaultValueSingleOption | CustomFieldContextSingleUserPickerDefaults | CustomFieldContextDefaultValueMultiUserPicker | CustomFieldContextDefaultValueSingleGroupPicker | CustomFieldContextDefaultValueMultipleGroupPicker | CustomFieldContextDefaultValueDate | CustomFieldContextDefaultValueDateTime | CustomFieldContextDefaultValueURL | CustomFieldContextDefaultValueProject | CustomFieldContextDefaultValueFloat | CustomFieldContextDefaultValueLabels | CustomFieldContextDefaultValueTextField | CustomFieldContextDefaultValueTextArea | CustomFieldContextDefaultValueReadOnly | CustomFieldContextDefaultValueSingleVersionPicker | CustomFieldContextDefaultValueMultipleVersionPicker | CustomFieldContextDefaultValueForgeStringField | CustomFieldContextDefaultValueForgeMultiStringField | CustomFieldContextDefaultValueForgeObjectField | CustomFieldContextDefaultValueForgeDateTimeField | CustomFieldContextDefaultValueForgeGroupField | CustomFieldContextDefaultValueForgeMultiGroupField | CustomFieldContextDefaultValueForgeNumberField | CustomFieldContextDefaultValueForgeUserField | CustomFieldContextDefaultValueForgeMultiUserField
5341453364

5341553365
"The default value for a cascading select custom field."
5341653366
type CustomFieldContextDefaultValueCascadingOption {
@@ -56867,7 +56817,7 @@ type WorkflowRules {
5686756817
}
5686856818

5686956819
"The workflow transition rule conditions tree."
56870-
union WorkflowCondition @discriminator(field: "nodeType") @discriminatorMapping(value: "simple", schema: "WorkflowSimpleCondition") @discriminatorMapping(value: "compound", schema: "WorkflowCompoundCondition") = WorkflowSimpleCondition | WorkflowCompoundCondition
56820+
union WorkflowCondition @discriminator(field: "nodeType", mapping: "{\\"simple\\":\\"WorkflowSimpleCondition\\",\\"compound\\":\\"WorkflowCompoundCondition\\"}") = WorkflowSimpleCondition | WorkflowCompoundCondition
5687156821

5687256822
"A workflow transition rule condition. This object returns \`nodeType\` as \`simple\`."
5687356823
type WorkflowSimpleCondition {
@@ -90579,7 +90529,7 @@ exports[`Schemas Pet should generate the correct schema: Pet 1`] = `
9057990529
query: Query
9058090530
}
9058190531

90582-
directive @discriminator(field: String) on INTERFACE | UNION
90532+
directive @discriminator(field: String, mapping: ObjMap) on INTERFACE | UNION
9058390533

9058490534
directive @globalOptions(sourceName: String, endpoint: String, operationHeaders: ObjMap, queryStringOptions: ObjMap, queryParams: ObjMap) on OBJECT
9058590535

0 commit comments

Comments
 (0)