GraphQL - делегирование схемы при сшивании схемы не работает, если возвращаемый тип Parent представляет собой список объектов

У меня есть объект Publication, который включает в себя imageId, который я хочу использовать для создания делегирования схемы и загрузки всего объекта.

Тип публикации определяется как:

const PublicationType = new GraphQLObjectType({
name: 'Publication',
description: 'Publication Type',
fields: () => ({
id: {
type: GraphQLID
},
callToAction: {
type: CallToActionType
},
userId: {
type: GraphQLID
},
groupId: {
type: GraphQLID
},
instruction: {
type: InstructionType
},
customizedTitle: {
type: GraphQLString
},
content: {
type: GraphQLString
},
activityType: {
type: ActivityType
},
creationTool: {
type: CreationTool
},
gift: {
type: GiftType
},
imageId: {
type: GraphQLInt
},
thumbnailId: {
type: GraphQLInt
},
createdAt: {
type: GraphQLInt
},
updatedAt: {
type: GraphQLInt
}
})
});

Тип носителя определяется как:

const MediaType = new GraphQLObjectType({
name: 'Media',
description: 'Media Object',
fields: () => ({
id: {
type: GraphQLInt
},
resource: {
type: GraphQLString
},
metadata: {
type: MetadataType
},
discr: {
type: GraphQLString
}
})
});

где MetadataType - это другой тип, определенный в коде.

2 объекта выставляются через эти запросы:

this._schema = new GraphQLObjectType({
name: 'Query',
description: 'Wall Query',
fields: () => ({
getGroupPublications: {
type: new GraphQLList(PublicationType),
args: {
groupId: {type: new GraphQLNonNull(GraphQLInt)},
from: {type: new GraphQLNonNull(GraphQLInt)},
to: {type: new GraphQLNonNull(GraphQLInt)},
},
resolve: (root, args, context) => PublicationResolver.groupPublications(context)
}
}),
});

А также

 this._schema = new GraphQLObjectType({
              name: 'Query',
              description: 'Media Query',
              fields: () => ({
                  getMedia: {
                      type: MediaType,
                      args: {
                          mediaId: {type: new GraphQLNonNull(GraphQLInt)}
                      },
                      resolve: (root, args, context) => MediaResolver.mediaLoader(context).load(args.mediaId)
                  }
              }),
          });

Теперь я пытаюсь объединить все схемы, которые определены, в одну схему и добавив делегирование для загрузки типа Media вместо ImageID, чтобы следующий класс представлял основную схему, которую я представлю:

import {mergeSchemas} from 'graphql-tools';
// other imports ...

class Services {

    private static _instance: Services;
    private _wall: PublicationService;
    private _media: MediaService;

    private constructor() {
        this._media = new MediaService();
        this._wall = new PublicationService();
    }

    public static Instance() {
        return this._instance || (this._instance = new this())
    }

    public MainSchema = async () => Promise.all([this._publication.schema, this._media.schema])
            .then(args => {
                const publicationSchema = args[0];
                const mediaSchema = args[1];

                const linkSchemaDefs = `
                                extend type Publication {
                                    image: Media
                                    thumbnail: Media
                                }`;

                return mergeSchemas({
                    schemas: [publicationSchema, mediaSchema, linkSchemaDefs],
                    resolvers: 
                        {
                            Publication: {
                                image: {
                                    fragment: `... on Publication { imageId }`,
                                    resolve(parent, args, context, info) {
                                        let mediaId = (parent.imageId === parseInt(parent.imageId, 10)) ? parent.imageId : 0;
                                        return info.mergeInfo.delegateToSchema({
                                            schema: mediaSchema,
                                            operation: 'query',
                                            fieldName: 'getMedia',
                                            args: {
                                                mediaId: mediaId,
                                            },
                                            context,
                                            info
                                        })
                                    }
                                },
                                thumbnail: {
                                    fragment: 'fragment PublicationThumbnailFragment on Publication { thumbnailId }',
                                    resolve(parent, args, context, info) {
                                        let mediaId = (parent.thumbnailId === parseInt(parent.thumbnailId, 10)) ? parent.thumbnailId : 0;
                                        return info.mergeInfo.delegateToSchema({
                                            schema: mediaSchema,
                                            operation: 'query',
                                            fieldName: 'getMedia',
                                            args: {
                                                mediaId: mediaId,
                                            },
                                            context,
                                            info
                                        })
                                    }
                                },
                            },
                        },
                });
            })
            .catch(error => Logger.Instance().error({
                    errorName: 'SchemaStitchingError',
                    logName: 'GraphQL Schema Stitching Error',
                    cause: error,
                    message: [`Services GraphQl Schema stitching rejected`],
                })
            );
}

export {Services}

основная схема будет предоставлена ​​конечному пользователю с помощью GraphQlExpress Server. Однако я мог видеть расширенный тип в определении схемы.

Тип публикации Схема Описание

Но когда я пытаюсь сделать запрос к изображению поля типа media, используя запрос, определенный как

query {
getGroupPublications(groupId:2, from: 1531180800,to: 1532276998) {
id
imageId
image {
resource
}
createdAt
}
}

запрос попадет непосредственно в публикации getGroupPublications без учета mergeSchema, и я получаю эту ошибку:

{ errors:
[ { Cannot query field "image" on type "Publication". Did you mean "imageId"?

GraphQL request (5:3)
4: imageId
5: image {
^
6: resource

at Object.Field (/home/docker/workspace/api-gateway/node_modules/graphql/validation/rules/FieldsOnCorrectType.js:65:31)
at Object.enter (/home/docker/workspace/api-gateway/node_modules/graphql/language/visitor.js:324:29)
at Object.enter (/home/docker/workspace/api-gateway/node_modules/graphql/language/visitor.js:366:25)
at visit (/home/docker/workspace/api-gateway/node_modules/graphql/language/visitor.js:254:26)
at visitUsingRules (/home/docker/workspace/api-gateway/node_modules/graphql/validation/validate.js:74:22)
at validate (/home/docker/workspace/api-gateway/node_modules/graphql/validation/validate.js:59:10)
at graphqlImpl (/home/docker/workspace/api-gateway/node_modules/graphql/graphql.js:106:50)
at /home/docker/workspace/api-gateway/node_modules/graphql/graphql.js:66:223
at new Promise ()
at Object.graphql (/home/docker/workspace/api-gateway/node_modules/graphql/graphql.js:63:10)
message: 'Cannot query field "image" on type "Publication". Did you mean "imageId"?',
locations: [Array],
path: undefined } ] }

Но если я запускаю свой запрос без изображения поля, он работает нормально

query {
getGroupPublications(groupId:1, from: 1531180800,to: 1532276998) {
id
imageId
}
}

1 ответ

Решение

Проблема, с которой я столкнулся, была связана с передачей полного запроса удаленной схеме, MergeSchema Resolver будет выполняться только после того, как удаленная схема вернет результаты.

Так в решателе getGroupPublications PublicationResolver.groupPublications(context) Я заменил поля, добавив расширение типа.

            let queryString = context.req.body.query;
            queryString = queryString.replace(/image[\s\r\n]*?{[^}]*}/gm, "");
            queryString = queryString.replace(/thumbnail[\s\r\n]*?{[^}]*}/gm, "");
            return graphql(schema, queryString,
                null,
                context,
                context.req.body.variables)
Другие вопросы по тегам