Skip to content

Commit

Permalink
Go
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Apr 3, 2023
1 parent 546cc10 commit d1e793f
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 101 deletions.
43 changes: 21 additions & 22 deletions packages/loaders/json-schema/src/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,27 +87,20 @@ export const DiscriminatorDirective = new GraphQLDirective({
field: {
type: GraphQLString,
},
},
});

export const DiscriminatorMappingDirective = new GraphQLDirective({
name: 'discriminatorMapping',
locations: [DirectiveLocation.INTERFACE, DirectiveLocation.UNION],
args: {
value: {
type: GraphQLString,
},
schema: {
type: GraphQLString,
mapping: {
type: ObjMapScalar,
},
},
});

export function processDiscriminatorAnnotations(
interfaceType: GraphQLInterfaceType,
fieldName: string,
) {
interfaceType.resolveType = root => root[fieldName];
export function processDiscriminatorAnnotations({
interfaceType,
discriminatorFieldName,
}: {
interfaceType: GraphQLInterfaceType;
discriminatorFieldName: string;
}) {
interfaceType.resolveType = root => root[discriminatorFieldName];
}

export const ResolveRootDirective = new GraphQLDirective({
Expand Down Expand Up @@ -570,7 +563,10 @@ export function processDirectives({
for (const directiveAnnotation of directiveAnnotations) {
switch (directiveAnnotation.name) {
case 'discriminator':
processDiscriminatorAnnotations(type, directiveAnnotation.args.field);
processDiscriminatorAnnotations({
interfaceType: type,
discriminatorFieldName: directiveAnnotation.args.field,
});
break;
}
}
Expand All @@ -579,6 +575,7 @@ export function processDirectives({
const directiveAnnotations = getDirectives(schema, type);
let statusCodeTypeNameIndexMap: Record<number, string>;
let discriminatorField: string;
let discriminatorMapping: Record<string, string>;
for (const directiveAnnotation of directiveAnnotations) {
switch (directiveAnnotation.name) {
case 'statusCodeTypeName':
Expand All @@ -588,14 +585,16 @@ export function processDirectives({
break;
case 'discriminator':
discriminatorField = directiveAnnotation.args.field;
discriminatorMapping = directiveAnnotation.args.mapping;
break;
}
}
type.resolveType = getTypeResolverFromOutputTCs(
type.getTypes(),
type.resolveType = getTypeResolverFromOutputTCs({
possibleTypes: type.getTypes(),
discriminatorField,
statusCodeTypeNameIndexMap,
);
discriminatorMapping,
statusCodeTypeNameMap: statusCodeTypeNameIndexMap,
});
}
if (isEnumType(type)) {
const directiveAnnotations = getDirectives(schema, type);
Expand Down
22 changes: 7 additions & 15 deletions packages/loaders/json-schema/src/getComposerFromJSONSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ import { sanitizeNameForGraphQL } from '@graphql-mesh/utils';
import {
DictionaryDirective,
DiscriminatorDirective,
DiscriminatorMappingDirective,
EnumDirective,
ExampleDirective,
LengthDirective,
Expand Down Expand Up @@ -738,26 +737,19 @@ export function getComposerFromJSONSchema(
}
if (subSchema.discriminator?.propertyName) {
schemaComposer.addDirective(DiscriminatorDirective);
const mappingByName: Record<string, string> = {};
for (const discriminatorValue in subSchema.discriminator.mapping) {
const ref = subSchema.discriminator.mapping[discriminatorValue];
const typeName = ref.replace('#/components/schemas/', '');
mappingByName[discriminatorValue] = typeName;
}
directives.push({
name: 'discriminator',
args: {
field: subSchema.discriminator.propertyName,
mapping: mappingByName,
},
});

if (subSchema.discriminator.mapping) {
schemaComposer.addDirective(DiscriminatorMappingDirective);
Object.keys(subSchema.discriminator.mapping).forEach(value => {
const mappedSchema = subSchema.discriminator.mapping[value].split('schemas/')[1];
directives.push({
name: 'discriminatorMapping',
args: {
value,
schema: mappedSchema,
},
});
});
}
}
const output = schemaComposer.createUnionTC({
name: getValidTypeName({
Expand Down
20 changes: 13 additions & 7 deletions packages/loaders/json-schema/src/getTypeResolverFromOutputTCs.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import { GraphQLObjectType, GraphQLTypeResolver } from 'graphql';
import { createGraphQLError } from '@graphql-tools/utils';

export function getTypeResolverFromOutputTCs(
possibleTypes: readonly GraphQLObjectType[],
discriminatorField?: string,
discriminatorMapping?: Record<string, string>,
statusCodeTypeNameMap?: Record<string, string>,
): GraphQLTypeResolver<any, any> {
export function getTypeResolverFromOutputTCs({
possibleTypes,
discriminatorField,
discriminatorMapping,
statusCodeTypeNameMap,
}: {
possibleTypes: readonly GraphQLObjectType[];
discriminatorField?: string;
discriminatorMapping?: Record<string, string>;
statusCodeTypeNameMap?: Record<string, string>;
}): GraphQLTypeResolver<any, any> {
return function resolveType(data: any) {
if (data.__typename) {
return data.__typename;
} else if (discriminatorField != null && data[discriminatorField]) {
return discriminatorMapping[data[discriminatorField]] || data[discriminatorField];
const discriminatorValue = data[discriminatorField];
return discriminatorMapping?.[discriminatorValue] || discriminatorValue;
}
if (data.$statusCode && statusCodeTypeNameMap) {
const typeName =
Expand Down
1 change: 1 addition & 0 deletions packages/loaders/openapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
},
"devDependencies": {
"@graphql-tools/utils": "9.2.1",
"@whatwg-node/fetch": "0.8.4",
"@whatwg-node/router": "0.3.0",
"graphql-yoga": "3.8.0",
"json-bigint-patch": "0.0.8"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Discriminator Mapping should generate correct schema: discriminator-mapping 1`] = `
"schema {
query: Query
}
directive @oneOf on OBJECT | INTERFACE
directive @discriminator(field: String, mapping: ObjMap) on INTERFACE | UNION
directive @globalOptions(sourceName: String, endpoint: String, operationHeaders: ObjMap, queryStringOptions: ObjMap, queryParams: ObjMap) on OBJECT
directive @httpOperation(path: String, operationSpecificHeaders: ObjMap, httpMethod: HTTPMethod, isBinary: Boolean, requestBaseBody: ObjMap, queryParamArgMap: ObjMap, queryStringOptionsByParam: ObjMap) on FIELD_DEFINITION
type Query @globalOptions(sourceName: "test") {
pets_by_id(id: String!): Pet @httpOperation(path: "/pets/{args.id}", operationSpecificHeaders: "{\\"accept\\":\\"application/json\\"}", httpMethod: GET)
}
union Pet @discriminator(field: "petType", mapping: "{\\"Dog\\":\\"DogDifferent\\",\\"Cat\\":\\"Cat\\"}") = Cat | DogDifferent
type Cat {
petType: String
cat_exclusive: String
}
type DogDifferent {
petType: String
dog_exclusive: String
}
scalar ObjMap
enum HTTPMethod {
GET
HEAD
POST
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
}"
`;
62 changes: 6 additions & 56 deletions packages/loaders/openapi/tests/__snapshots__/schemas.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -41929,52 +41929,6 @@ enum HTTPMethod {
}"
`;

exports[`Schemas DiscriminatorMapping should generate the correct schema: DiscriminatorMapping 1`] = `
"schema {
query: Query
}

directive @oneOf on OBJECT | INTERFACE

directive @discriminator(field: String) on INTERFACE | UNION

directive @discriminatorMapping(value: String, schema: String) on INTERFACE | UNION

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

directive @httpOperation(path: String, operationSpecificHeaders: ObjMap, httpMethod: HTTPMethod, isBinary: Boolean, requestBaseBody: ObjMap, queryParamArgMap: ObjMap, queryStringOptionsByParam: ObjMap) on FIELD_DEFINITION

type Query @globalOptions(sourceName: "DiscriminatorMapping") {
pets_by_id(id: String!): Pet @httpOperation(path: "/pets/{args.id}", operationSpecificHeaders: "{\\"accept\\":\\"application/json\\"}", httpMethod: GET)
}

union Pet @discriminator(field: "petType") @discriminatorMapping(value: "Dog", schema: "DogDifferent") @discriminatorMapping(value: "Cat", schema: "Cat") = Cat | DogDifferent

type Cat {
petType: String
cat_exclusive: String
}

type DogDifferent {
petType: String
dog_exclusive: String
}

scalar ObjMap

enum HTTPMethod {
GET
HEAD
POST
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
}"
`;

exports[`Schemas GitHub should generate the correct schema: GitHub 1`] = `
"schema {
query: Query
Expand Down Expand Up @@ -49695,9 +49649,7 @@ directive @example(value: ObjMap) repeatable on FIELD_DEFINITION | OBJECT | INPU

directive @oneOf on OBJECT | INTERFACE

directive @discriminator(field: String) on INTERFACE | UNION

directive @discriminatorMapping(value: String, schema: String) on INTERFACE | UNION
directive @discriminator(field: String, mapping: ObjMap) on INTERFACE | UNION

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

Expand Down Expand Up @@ -49740,7 +49692,7 @@ type TicketMessageGet {
Author: PersonGet @link(defaultRootType: "Mutation", defaultField: "TicketMessagesUpdateTicketMessage")
}

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

type CompanyGet {
_resolveType: company_const!
Expand Down Expand Up @@ -50388,9 +50340,7 @@ directive @resolveRoot on FIELD_DEFINITION

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

directive @discriminator(field: String) on INTERFACE | UNION

directive @discriminatorMapping(value: String, schema: String) on INTERFACE | UNION
directive @discriminator(field: String, mapping: ObjMap) on INTERFACE | UNION

directive @dictionary on FIELD_DEFINITION

Expand Down Expand Up @@ -53410,7 +53360,7 @@ type PageBeanCustomFieldContextDefaultValue {
values: [CustomFieldContextDefaultValue]
}

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
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

"The default value for a cascading select custom field."
type CustomFieldContextDefaultValueCascadingOption {
Expand Down Expand Up @@ -56867,7 +56817,7 @@ type WorkflowRules {
}

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

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

directive @discriminator(field: String) on INTERFACE | UNION
directive @discriminator(field: String, mapping: ObjMap) on INTERFACE | UNION

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

Expand Down
Loading

0 comments on commit d1e793f

Please sign in to comment.