当前位置: 首页 > 知识库问答 >
问题:

模式拼接通过添加前缀解决冲突

戴树
2023-03-14

我有两个模式

方案1

type Permission {
    relation: Relation
}

enum Relation {
    ONE
    TWO
    THREE
}

架构

type Permission {
    relation: Relation
}

enum Relation {
    FOUR
    FIVE
    SIX
}  

预期结果类似于:(但我对不同的想法持开放态度)我希望在合并后进行的查询如下:

{
    permissions{
        relation
    }
}

结果是

"permissions": [
  {
    "relation": "ONE"
  },
  {
    "relation": "SIX"
  }
]

"permissions": [
  {
    "relation": "schema1ONE"
  },
  {
    "relation": "schema2SIX"
  }
]

还有突变,比如:

mutation{
  createPermission(
    relation: ONE
  ){
    relation
  }
}

mutation{
  createPermission(
    relation: SIX
  ){
    relation
  }
}

mutation{
  createPermission(
    relation: schema1ONE
  ){
    relation
  }
}

mutation{
  createPermission(
    relation: schema2SIX
  ){
    relation
  }
}

我正在尝试在graphql工具上使用transformSchema函数,但无法完全正确地理解它:

const Schema1 = await getRemoteSchema('schema1_url', 'schema1');
const Schema2 = await getRemoteSchema('schema2_url', 'schema2');

const schemas = [Schema1, Schema2]

const schema = mergeSchemas({
  schemas: schemas,
  resolvers: {}
});

getRemoteSchema定义

export const getRemoteSchema = async (uri: string, schemaName: string): Promise<GraphQLSchema> => {
  const httpLink = new HttpLink({ uri, fetch });

  const schema = await introspectSchema(httpLink);

  const executableSchema = makeRemoteExecutableSchema({
    schema,
    httpLink,
  });

  // transform schema by renaming root fields and types
  const renamedSchema = transformSchema(
    executableSchema,
    [
      new RenameTypes(name => {
        if (name == 'Relation') {
          return schemaName + name
        } else {
          return name
        }
      }),
      // new RenameRootFields((operation, name) => `${schemaName}_${name}`)
    ]
  );

  return renamedSchema;
}    

我犯了这个小毛病https://glitch.com/edit/#!/模式缝合冲突,因此更容易看到问题。

共有2个答案

糜宜民
2023-03-14

目前,我看不到使用graphql工具实现所需行为的简单方法,因为在mergeSchemas()的实现中,onTypeConflict选项最初被弃用,后来被删除,即使它仍然存在于公共界面上。使用该选项,我们可以简单地传递一个回调,该回调知道冲突的类型及其对应的AST。

transformSchema()但是,当您尝试使用它时,它只会重命名枚举类型名称,而不会重命名枚举值。您很可能需要实现自己的转换,而不是使用预定义的转换来实现您的目标。不过,我建议大家看看ConvertEnumValues的实现。在实现自己的转换时,这可能会让您更好地了解如何根据需要行走和操作AST。

例如,我会考虑一个实现,它跟踪所有的代码> GraphQlEnumTypes <代码>,如果遇到名称冲突,就会看到并深深地合并它们。您可以使用模块范围内的变量进行跟踪,也可以使用转换中的实例属性进行跟踪。如果使用后者,请不要忘记预先实例化它,并通过引用将其传递给后续的tranformSchema()调用。

解阳泽
2023-03-14

您需要RenameTypesRenameRootFields转换,RenameTypes来转换类型名

from:权限关系(冲突类型),

至:schema1\u权限schema2\u权限

和:schema1\u关系schema1\u关系

RenameRootFields转换这些类型的查询名称

发件人:权限(id:id!):权限

到:schema1\u权限(id:id!):schema1_权限schema2_权限(id:id!):方案2_权限

和:权限:[权限]

收件人:schema1\u权限:[schema1\u权限]schema2\u权限:[schema2\u权限]

转换将类似于:

const {
  makeExecutableSchema,
  addMockFunctionsToSchema,
  transformSchema,
  RenameTypes,
  RenameRootFields
} = require('graphql-tools');

const schema1 = makeExecutableSchema({
  typeDefs: `
    type Permission {
      id: ID!
      text: String
      relation: Relation
    }

    type Query {
      permissions: [Permission]
      permission(id: ID!): Permission
    }

    enum Relation {
      ONE
      TWO
      THREE
    }
  `
});

addMockFunctionsToSchema({ schema: schema1 });

const renamedSchema1 = transformSchema(
  schema1,
  [
    new RenameTypes(name => {
      if (name == 'Relation' || name == 'Permission') {
        return 'schema1_' + name
      } else {
        return name
      }
    }, { renameBuiltins: false, renameScalars: true }),
    new RenameRootFields((_op, name) => {
      return name.includes('ermission') ? `schema1_${name}` : name
    })
  ]
);

参考资料:https://www.apollographql.com/docs/graphql-tools/schema-transforms/ https://www.apollographql.com/docs/graphql-tools/schema-stitching/

 类似资料:
  • 我有一个关于GraphQL模式拼接的问题。我有两个Graphql模式: 和 我现在尝试使用graphql工具的函数合并模式: 但不是我想要实现的(扩展用户类型): 结果是:type Name{firstname:String!lastname:String!} 在最终架构中只显示一个UserType。我尝试使用中的API来扩展Type,但没有得到任何结果。 有没有办法通过扩展冲突类型来合并模式?

  • 我目前正在做codingbat问题的乐趣,我刚刚做了这个问题。 “给定一个字符串,考虑由字符串的前N个字符组成的前缀字符串。该前缀字符串是否出现在字符串的其他地方?假设字符串不是空的,并且N在1..str.length()的范围内。前缀再次(”abxyabc“,1)→真前缀再次(”abxyabc“,2)→真前缀再次(”abxyabc“,3)→假”http://codingbat.com/prob/

  • 我有一个包含许多列的表,我希望为每个列添加前缀。 我尝试了以下查询:

  • 写了一个npm包,father打包,担心其中的css会影响到业务方,怎么快速给类名添加统一前缀

  • 好的,所以我最近读了很多关于的文章,我认为有些人让它比实际更令人困惑。我想知道这个过程是否正确。 因此,当您有一个键和值时,例如出生于 1805-02-13 的彼得·狄利克雷,在这种情况下,将是和“ 第一步是在上使用哈希函数,即。让我们假设哈希函数生成这个值到bucket nr<code>5</code>。这意味着在该特定桶中,索引上,键/值对将被存储。 因此,如果我们想检索这些信息,我们使用并且

  • 我有jdk 1.7的java代码,如下所示,它是基于并行线程的实现 Executors.new修复线程池;executorService.execute(可运行的)某个对象); 在日志中,我得到的线程名称如下 池-2-线程-1池-2线程-2池-1线程-1池-1线程-2 我想在它们后面加上一些字符串