我们可以使用 GraphQL Schema Language 中的 buildSchema 函数将 GraphQL schema 转换为可操作的对象,并使用 introspection 查询获取 schema 的信息。通过遍历 schema 中的所有 Scalar 类型,我们可以建立一个每个 Scalar 的祖先及子孙关系图。
下面是一个示例代码:
const { buildClientSchema, getIntrospectionQuery, graphqlSync } = require("graphql");
const schema = buildClientSchema(yourGraphQLSchema);
const introspectionQuery = getIntrospectionQuery();
const introspectionRes = graphqlSync(schema, introspectionQuery);
const typeMap = introspectionRes.data.__schema.types.reduce((acc, type) => {
if (type.kind === "SCALAR") {
acc[type.name] = {
ancestors: [],
descendants: [],
};
}
return acc;
}, {});
function addAncestorsAndDescendants(typeMap) {
Object.keys(typeMap).forEach((typeName) => {
const type = schema.getType(typeName);
const literalNodes = type.astNode.type.annotation;
const ancestors = getTypeNames(literalNodes)
.filter((name) => typeMap[name])
.map((name) => typeMap[name]);
const descendants = Object.values(schema.getTypeMap())
.filter((t) => t.astNode && getTypeNames(t.astNode.type.annotation).includes(typeName))
.filter((t) => t.astNode.type.kind === "NamedType" && typeMap[t.name])
.map((t) => typeMap[t.name]);
typeMap[typeName].ancestors = ancestors;
typeMap[typeName].descendants = descendants;
});
}
function getTypeNames(node) {
if (node.kind === "NamedType") {
return [node.name.value];
} else if (node.kind === "NonNullType" || node.kind === "ListType") {
return getTypeNames(node.type);
} else {
return node.types.flatMap(getTypeNames);
}
}
addAncestorsAndDescendants(typeMap);
console.log(typeMap);
这个示例将注释为 Scalar
类型的每个类型的祖先和后代存储在 typeMap
中,以便在需要时使用。