NodeJS 有没有办法将graphql查询字符串转换为GraphQLResolveInfo对象?

p1tboqfb  于 2023-06-05  发布在  Node.js
关注(0)|答案(2)|浏览(197)

我写了一个软件,它解析和格式化了graphql解析器函数的第四个参数(info对象),以便在其他地方使用。我想为这个软件写单元测试。具体来说,我不想自己构建GraphQLResolveInfo对象,因为这样做非常麻烦、容易出错并且难以维护。相反,我想编写人类可读的查询字符串,并将它们转换为GraphQLResolveInfo对象,以便将它们传递给我的软件。
在广泛的谷歌搜索和阅读graphql-js源代码之后,我还没有找到一种简单的方法来完成他们在内部所做的事情。我真的希望我错过了什么。
我并不打算使用graphql-tag库,因为这只会生成一个与GraphQLResolveInfo类型格式完全不同的AST。
以前有人这么做过吗?帮助将不胜感激!

a0x5cqrl

a0x5cqrl1#

我将继续关注这个问题,看看是否会沿着更好的答案,但我最终设法解决了我的特定问题,根据我的特定用例的需要,创建了GraphQLResolveInfo对象的近似值。
GraphQLResolveInfo对象由多个属性组成,其中两个属性称为fieldNodesfragments。实际上,两者都是graphql-tag从查询字符串生成的相同AST的一部分。这些是GraphQLResolveInfo对象中与我编写的软件有关的部分,其余部分被忽略。
所以我是这么做的:

import gql from 'graphql-tag';

// The converter function
const convertQueryToResolveInfo = (query) => {
    const operation = query.definitions
        .find(({ kind }) => kind === 'OperationDefinition');
    const fragments = query.definitions
        .filter(({ kind }) => kind === 'FragmentDefinition')
        .reduce((result, current) => ({
            ...result,
            [current.name.value]: current,
        }), {});

    return {
        fieldNodes: operation.selectionSet.selections,
        fragments,
    };
};

// An example call
const query = gql`
    query {
        foo {
            bar
        }
    }
`;
const info = convertQueryToResolveInfo(query);

graphql-tag生成的AST中,我提取并修改了操作和片段定义,使它们看起来与在GraphQLResolveInfo对象中一样。这绝不是完美的,可能会在未来根据我的软件如何发展而改变,但它是我的特定问题的相对简短的解决方案。

3duebb1j

3duebb1j2#

我最近不得不这样做,以便将REST端点添加到我的服务器上,因为ChatGPT插件不支持GraphQL。这是我想到的:

import { DocumentNode, FieldNode, FragmentDefinitionNode, GraphQLResolveInfo, OperationDefinitionNode } from "graphql";

const gqlToGraphQLResolveInfo = (query: DocumentNode, path: string): GraphQLResolveInfo => {
    const operation: OperationDefinitionNode | undefined = query.definitions
        .find(({ kind }) => kind === "OperationDefinition") as OperationDefinitionNode;

    const fragmentDefinitions = query.definitions
        .filter(({ kind }) => kind === "FragmentDefinition") as FragmentDefinitionNode[];

    const fragments: { [key: string]: FragmentDefinitionNode } = fragmentDefinitions
        .reduce((result, current: FragmentDefinitionNode) => ({
            ...result,
            [current.name.value]: current,
        }), {});

    const fieldNodes: FieldNode[] = operation?.selectionSet.selections as FieldNode[];

    const resolveInfo: GraphQLResolveInfo = {
        fieldName: fieldNodes[0]?.name.value || "",
        fieldNodes,
        returnType: null,
        parentType: null,
        schema: null,
        fragments,
        rootValue: {},
        operation,
        variableValues: {},
        path: {
            prev: undefined,
            key: path,
        },
    } as any;
    return resolveInfo;
};

相关问题