Skip to content

Commit

Permalink
Feature: add support for interface resolution (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
MatteoGranziera authored Apr 8, 2023
1 parent d8b8266 commit 626361d
Show file tree
Hide file tree
Showing 3 changed files with 1,074 additions and 6 deletions.
56 changes: 50 additions & 6 deletions lib/federation.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ const {
isTypeDefinitionNode,
isTypeExtensionNode,
isObjectType,
isInterfaceType,
isSpecifiedDirective,
defaultTypeResolver,
GraphQLDirective
} = require('graphql')
const { validateSDL } = require('graphql/validation/validate')
Expand Down Expand Up @@ -173,6 +175,35 @@ function addTypeNameToResult (result, typename) {
return result
}

function resolveType (reference, context, info) {
const { __typename } = reference

const type = info.schema.getType(__typename)

if (!type || !(isObjectType(type) || isInterfaceType(type))) {
throw new MER_ERR_GQL_FEDERATION_INVALID_SCHEMA(__typename)
}

if (!isInterfaceType(type)) {
return type
}

const resolveTypeFn = type.resolveType || defaultTypeResolver

const resolveType = resolveTypeFn({
...reference,
__typename: undefined
}, context, info, type)

if (typeof resolveType !== 'string' && typeof resolveType.then === 'function') {
return resolveType.then((resolvedTypename) =>
info.schema.getType(resolvedTypename)
)
}

return info.schema.getType(resolveType)
}

function addEntitiesResolver (schema) {
const entityTypes = Object.values(schema.getTypeMap()).filter(
type => isObjectType(type) && typeIncludesDirective(type, 'key')
Expand All @@ -199,12 +230,24 @@ function addEntitiesResolver (schema) {
...queryFields._entities,
resolve: (_source, { representations }, context, info) => {
return representations.map(reference => {
const { __typename } = reference
const type = resolveType(reference, context, info)

if (type && typeof type.then === 'function') {
return type.then((resolvedType) => {
const resolveReference = resolvedType.resolveReference ||
function defaultResolveReference () {
return reference
}

const result = resolveReference(reference, {}, context, info)

const type = info.schema.getType(__typename)
if (result && typeof result.then === 'function') {
return result.then((x) =>
addTypeNameToResult(x, resolvedType.name))
}

if (!type || !isObjectType(type)) {
throw new MER_ERR_GQL_FEDERATION_INVALID_SCHEMA(__typename)
return addTypeNameToResult(result, resolvedType.name)
})
}

const resolveReference = type.resolveReference
Expand All @@ -216,10 +259,11 @@ function addEntitiesResolver (schema) {
const result = resolveReference(reference, {}, context, info)

if (result && 'then' in result && typeof result.then === 'function') {
return result.then(x => addTypeNameToResult(x, __typename))
return result.then((x) =>
addTypeNameToResult(x, type.name))
}

return addTypeNameToResult(result, __typename)
return addTypeNameToResult(result, type.name)
})
}
}
Expand Down
Loading

0 comments on commit 626361d

Please sign in to comment.