Cms: GraphQL: Plugin added Interfaces don't get their type generators called

Created on 23 Oct 2019  路  1Comment  路  Source: craftcms/cms

SEOmatic (and Retour) both register GraphQL Interfaces -- which define generators that return objects for GraphQL to use.

The issue is here:

https://github.com/craftcms/cms/blob/develop/src/services/Gql.php#L232

            // Create a pre-built schema if that's what they want.
            $interfaces = [
                EntryInterface::class,
                MatrixBlockInterface::class,
                AssetInterface::class,
                UserInterface::class,
                GlobalSetInterface::class,
                ElementInterface::class,
                CategoryInterface::class,
                TagInterface::class,
            ];
            foreach ($interfaces as $interfaceClass) {
                if (!is_subclass_of($interfaceClass, InterfaceType::class)) {
                    throw new GqlException('Incorrectly defined interface ' . $interfaceClass);
                }
                /** @var GeneratorInterface $typeGeneratorClass */
                $typeGeneratorClass = $interfaceClass::getTypeGenerator();
                foreach ($typeGeneratorClass::generateTypes() as $type) {
                    $schemaConfig['types'][] = $type;
                }
            }

Craft iterates through a hard-coded list of Interfaces, and generates the the types for them... but since plugins are not given a chance to be added to said hard-coded list, they fail.

This is a "soft error" in the GraphQL implementation in Craft, but the Apollo layer added via Gatsby and Gridsome do additional type checking to ensure that the returned data matches a registered type:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var graphql_1 = require("graphql");
function resolveFromParentTypename(parent, schema) {
    var parentTypename = parent['__typename'];
    if (!parentTypename) {
        throw new Error('Did not fetch typename for object, unable to resolve interface.');
    }
    var resolvedType = schema.getType(parentTypename);
    if (!(resolvedType instanceof graphql_1.GraphQLObjectType)) {
        throw new Error('__typename did not match an object type: ' + parentTypename + ' -- ' + JSON.stringify(schema));
    }
    return resolvedType;
}
exports.default = resolveFromParentTypename;
//# sourceMappingURL=resolveFromParentTypename.js.map

...which fails, throwing an error.

I manually added my SeomaticInterface to the hard-coded list above, and everything worked peachy:

Screen Shot 2019-10-23 at 1 28 49 AM

Ref: https://github.com/nystudio107/craft-seomatic/issues/487#issuecomment-545273426

Most helpful comment

The beer is on me when we next meet, @khalwat.

>All comments

The beer is on me when we next meet, @khalwat.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

michaelhue picture michaelhue  路  3Comments

leigeber picture leigeber  路  3Comments

davist11 picture davist11  路  3Comments

timkelty picture timkelty  路  3Comments

brandonkelly picture brandonkelly  路  3Comments