@theguild/federation-composition
Version:
Open Source Composition library for Apollo Federation
984 lines (983 loc) • 32.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSchemaNode = createSchemaNode;
exports.createDirectiveNode = createDirectiveNode;
exports.createObjectTypeNode = createObjectTypeNode;
exports.createInterfaceTypeNode = createInterfaceTypeNode;
exports.createInputObjectTypeNode = createInputObjectTypeNode;
exports.createUnionTypeNode = createUnionTypeNode;
exports.createEnumTypeNode = createEnumTypeNode;
exports.createScalarTypeNode = createScalarTypeNode;
exports.createJoinGraphEnumTypeNode = createJoinGraphEnumTypeNode;
exports.schemaCoordinate = schemaCoordinate;
exports.stripFederation = stripFederation;
const graphql_1 = require("graphql");
const printer_js_1 = require("../../graphql/printer.js");
const state_js_1 = require("../../subgraph/state.js");
function createSchemaNode(schema) {
return {
kind: graphql_1.Kind.SCHEMA_DEFINITION,
directives: schema.links?.map(createLinkDirectiveNode),
operationTypes: [].concat(schema.query
? {
kind: graphql_1.Kind.OPERATION_TYPE_DEFINITION,
operation: graphql_1.OperationTypeNode.QUERY,
type: createNamedTypeNode(schema.query),
}
: [], schema.mutation
? {
kind: graphql_1.Kind.OPERATION_TYPE_DEFINITION,
operation: graphql_1.OperationTypeNode.MUTATION,
type: createNamedTypeNode(schema.mutation),
}
: [], schema.subscription
? {
kind: graphql_1.Kind.OPERATION_TYPE_DEFINITION,
operation: graphql_1.OperationTypeNode.SUBSCRIPTION,
type: createNamedTypeNode(schema.subscription),
}
: []),
};
}
function createDirectiveNode(directive) {
return {
kind: graphql_1.Kind.DIRECTIVE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: directive.name,
},
locations: Array.from(directive.locations).map(location => ({
kind: graphql_1.Kind.NAME,
value: location,
})),
repeatable: directive.repeatable,
arguments: directive.arguments.map(createFieldArgumentNode),
};
}
function createObjectTypeNode(objectType) {
return {
kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: objectType.name,
},
directives: applyDirectives(objectType),
fields: objectType.fields.map(createFieldNode),
description: objectType.description ? createDescriptionNode(objectType.description) : undefined,
interfaces: objectType.interfaces?.map(createNamedTypeNode),
};
}
function createInterfaceTypeNode(interfaceType) {
return {
kind: graphql_1.Kind.INTERFACE_TYPE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: interfaceType.name,
},
directives: applyDirectives(interfaceType),
description: interfaceType.description
? createDescriptionNode(interfaceType.description)
: undefined,
fields: interfaceType.fields.map(createFieldNode),
interfaces: interfaceType.interfaces?.map(createNamedTypeNode),
};
}
function createInputObjectTypeNode(inputObjectType) {
return {
kind: graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: inputObjectType.name,
},
directives: applyDirectives(inputObjectType),
fields: inputObjectType.fields.map(createInputFieldNode),
description: inputObjectType.description
? createDescriptionNode(inputObjectType.description)
: undefined,
};
}
function createUnionTypeNode(unionType) {
return {
kind: graphql_1.Kind.UNION_TYPE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: unionType.name,
},
directives: applyDirectives(unionType),
description: unionType.description ? createDescriptionNode(unionType.description) : undefined,
types: unionType.members.map(member => ({
kind: graphql_1.Kind.NAMED_TYPE,
name: {
kind: graphql_1.Kind.NAME,
value: member,
},
})),
};
}
function createEnumTypeNode(enumType) {
return {
kind: graphql_1.Kind.ENUM_TYPE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: enumType.name,
},
directives: applyDirectives(enumType),
description: enumType.description ? createDescriptionNode(enumType.description) : undefined,
values: enumType.values.map(createEnumValueNode),
};
}
function createScalarTypeNode(scalarType) {
return {
kind: graphql_1.Kind.SCALAR_TYPE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: scalarType.name,
},
description: scalarType.description ? createDescriptionNode(scalarType.description) : undefined,
directives: applyDirectives(scalarType),
};
}
function createJoinGraphEnumTypeNode(graphs) {
return createEnumTypeNode({
name: 'join__Graph',
cost: null,
values: graphs.map(graph => ({
name: graph.enumValue,
ast: {
directives: [createJoinGraphDirectiveNode(graph)],
},
})),
});
}
function createFieldNode(field) {
return {
kind: graphql_1.Kind.FIELD_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: field.name,
},
type: (0, graphql_1.parseType)(field.type),
directives: applyDirectives(field),
description: field.description ? createDescriptionNode(field.description) : undefined,
arguments: field.arguments?.map(createFieldArgumentNode),
};
}
function createInputFieldNode(inputField) {
return {
kind: graphql_1.Kind.INPUT_VALUE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: inputField.name,
},
type: (0, graphql_1.parseType)(inputField.type),
directives: applyDirectives(inputField),
description: inputField.description ? createDescriptionNode(inputField.description) : undefined,
defaultValue: typeof inputField.defaultValue === 'string'
? (0, graphql_1.parseConstValue)(inputField.defaultValue)
: undefined,
};
}
function createEnumValueNode(enumValue) {
return {
kind: graphql_1.Kind.ENUM_VALUE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: enumValue.name,
},
directives: applyDirectives(enumValue),
description: enumValue.description ? createDescriptionNode(enumValue.description) : undefined,
};
}
function createDefaultValue(defaultValue, kind) {
if (typeof defaultValue !== 'string') {
return undefined;
}
if (kind === state_js_1.ArgumentKind.ENUM) {
return {
kind: graphql_1.Kind.ENUM,
value: defaultValue.startsWith(`"`) && defaultValue.endsWith(`"`)
? defaultValue.substring(1, defaultValue.length - 1)
: defaultValue,
};
}
return (0, graphql_1.parseConstValue)(defaultValue);
}
function createFieldArgumentNode(argument) {
return {
kind: graphql_1.Kind.INPUT_VALUE_DEFINITION,
name: {
kind: graphql_1.Kind.NAME,
value: argument.name,
},
defaultValue: createDefaultValue(argument.defaultValue, argument.kind),
type: (0, graphql_1.parseType)(argument.type),
directives: applyDirectives(argument),
description: argument.description ? createDescriptionNode(argument.description) : undefined,
};
}
function createJoinTypeDirectiveNode(join) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'join__type',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'graph',
},
value: {
kind: graphql_1.Kind.ENUM,
value: join.graph,
},
},
join.key
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'key',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.key,
},
}
: null,
join.resolvable === false
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'resolvable',
},
value: {
kind: graphql_1.Kind.BOOLEAN,
value: false,
},
}
: null,
join.isInterfaceObject
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'isInterfaceObject',
},
value: {
kind: graphql_1.Kind.BOOLEAN,
value: true,
},
}
: null,
join.extension
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'extension',
},
value: {
kind: graphql_1.Kind.BOOLEAN,
value: true,
},
}
: null,
].filter(nonEmpty),
};
}
function createJoinImplementsDirectiveNode(join) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'join__implements',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'graph',
},
value: {
kind: graphql_1.Kind.ENUM,
value: join.graph,
},
},
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'interface',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.interface,
},
},
],
};
}
function createJoinFieldDirectiveNode(join) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'join__field',
},
arguments: [
join.graph
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'graph',
},
value: {
kind: graphql_1.Kind.ENUM,
value: join.graph,
},
}
: null,
join.type
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'type',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.type,
},
}
: null,
join.override
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'override',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.override,
},
}
: null,
join.usedOverridden
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'usedOverridden',
},
value: {
kind: graphql_1.Kind.BOOLEAN,
value: true,
},
}
: null,
join.external
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'external',
},
value: {
kind: graphql_1.Kind.BOOLEAN,
value: true,
},
}
: null,
join.provides
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'provides',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.provides,
},
}
: null,
join.requires
? {
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'requires',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.requires,
},
}
: null,
].filter(nonEmpty),
};
}
function createJoinUnionMemberDirectiveNode(join) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'join__unionMember',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'graph',
},
value: {
kind: graphql_1.Kind.ENUM,
value: join.graph,
},
},
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'member',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.member,
},
},
],
};
}
function createJoinEnumValueDirectiveNode(join) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'join__enumValue',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'graph',
},
value: {
kind: graphql_1.Kind.ENUM,
value: join.graph,
},
},
],
};
}
function createInaccessibleDirectiveNode() {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'inaccessible',
},
arguments: [],
};
}
function createAuthenticatedDirectiveNode() {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'authenticated',
},
arguments: [],
};
}
function deduplicatePoliciesOrScopes(items) {
const stringified = items.map(group => group.sort().join('ɵ'));
const indexesToRemove = [];
for (let index = 0; index < stringified.length; index++) {
if (stringified.indexOf(stringified[index]) !== index) {
indexesToRemove.push(index);
}
}
return items.filter((_, index) => !indexesToRemove.includes(index));
}
function createPolicyDirectiveNode(policies) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'policy',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'policies',
},
value: {
kind: graphql_1.Kind.LIST,
values: deduplicatePoliciesOrScopes(policies).map(group => ({
kind: graphql_1.Kind.LIST,
values: group.map(policy => ({
kind: graphql_1.Kind.STRING,
value: policy,
})),
})),
},
},
],
};
}
function createRequiresScopesDirectiveNode(scopes) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'requiresScopes',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'scopes',
},
value: {
kind: graphql_1.Kind.LIST,
values: deduplicatePoliciesOrScopes(scopes).map(group => ({
kind: graphql_1.Kind.LIST,
values: group.map(scope => ({
kind: graphql_1.Kind.STRING,
value: scope,
})),
})),
},
},
],
};
}
function createTagDirectiveNode(name) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'tag',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'name',
},
value: {
kind: graphql_1.Kind.STRING,
value: name,
},
},
],
};
}
function createJoinGraphDirectiveNode(join) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'join__graph',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'name',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.name,
},
},
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'url',
},
value: {
kind: graphql_1.Kind.STRING,
value: join.url ?? '',
},
},
],
};
}
function createDescriptionNode(description) {
return {
kind: graphql_1.Kind.STRING,
value: description.value,
block: true,
};
}
function createDeprecatedDirectiveNode(deprecated) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'deprecated',
},
arguments: typeof deprecated.reason === 'string'
? [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'reason',
},
value: {
kind: graphql_1.Kind.STRING,
value: deprecated.reason,
},
},
]
: [],
};
}
function createSpecifiedByDirectiveNode(url) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'specifiedBy',
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'url',
},
value: {
kind: graphql_1.Kind.STRING,
value: url,
},
},
],
};
}
function createCostDirectiveNode(input) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: input.directiveName,
},
arguments: [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'weight',
},
value: {
kind: graphql_1.Kind.INT,
value: String(input.cost),
},
},
],
};
}
function createListSizeDirectiveNode(input) {
const args = [];
if (input.requireOneSlicingArgument === false) {
args.push({
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'requireOneSlicingArgument',
},
value: {
kind: graphql_1.Kind.BOOLEAN,
value: false,
},
});
}
if (typeof input.assumedSize === 'number') {
args.push({
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'assumedSize',
},
value: {
kind: graphql_1.Kind.INT,
value: String(input.assumedSize),
},
});
}
if (Array.isArray(input.slicingArguments)) {
args.push({
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'slicingArguments',
},
value: {
kind: graphql_1.Kind.LIST,
values: input.slicingArguments.map(arg => ({
kind: graphql_1.Kind.STRING,
value: arg,
})),
},
});
}
if (Array.isArray(input.sizedFields)) {
args.push({
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'sizedFields',
},
value: {
kind: graphql_1.Kind.LIST,
values: input.sizedFields.map(arg => ({
kind: graphql_1.Kind.STRING,
value: arg,
block: false,
})),
},
});
}
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: input.directiveName,
},
arguments: args,
};
}
function createLinkDirectiveNode(link) {
return {
kind: graphql_1.Kind.DIRECTIVE,
name: {
kind: graphql_1.Kind.NAME,
value: 'link',
},
arguments: [].concat([
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'url',
},
value: {
kind: graphql_1.Kind.STRING,
value: link.url,
},
},
], link.for
? [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'for',
},
value: {
kind: graphql_1.Kind.ENUM,
value: link.for,
},
},
]
: [], link.import
? [
{
kind: graphql_1.Kind.ARGUMENT,
name: {
kind: graphql_1.Kind.NAME,
value: 'import',
},
value: {
kind: graphql_1.Kind.LIST,
values: link.import.map(imported => {
if (imported.alias) {
return {
kind: graphql_1.Kind.OBJECT,
fields: [
{
kind: graphql_1.Kind.OBJECT_FIELD,
name: {
kind: graphql_1.Kind.NAME,
value: 'name',
},
value: {
kind: graphql_1.Kind.STRING,
value: imported.name,
},
},
],
};
}
return {
kind: graphql_1.Kind.STRING,
value: imported.name,
};
}),
},
},
]
: []),
};
}
function createNamedTypeNode(name) {
return {
kind: graphql_1.Kind.NAMED_TYPE,
name: {
kind: graphql_1.Kind.NAME,
value: name,
},
};
}
function applyDirectives(common) {
const deduplicatedDirectives = (common.ast?.directives ?? [])
.map(directive => {
return {
ast: directive,
string: (0, printer_js_1.print)(directive),
};
})
.filter((directive, index, all) => all.findIndex(d => d.string === directive.string) === index)
.map(d => d.ast);
return [].concat(deduplicatedDirectives, common.join?.type?.map(createJoinTypeDirectiveNode) ?? [], common.join?.implements?.map(createJoinImplementsDirectiveNode) ?? [], common.join?.field?.map(createJoinFieldDirectiveNode) ?? [], common.join?.unionMember?.map(createJoinUnionMemberDirectiveNode) ?? [], common.join?.enumValue?.map(createJoinEnumValueDirectiveNode) ?? [], common.tags?.map(createTagDirectiveNode) ?? [], common.inaccessible ? [createInaccessibleDirectiveNode()] : [], common.authenticated ? [createAuthenticatedDirectiveNode()] : [], common.policies?.length ? [createPolicyDirectiveNode(common.policies)] : [], common.scopes?.length ? [createRequiresScopesDirectiveNode(common.scopes)] : [], common.cost ? [createCostDirectiveNode(common.cost)] : [], common.listSize ? [createListSizeDirectiveNode(common.listSize)] : [], common.deprecated ? [createDeprecatedDirectiveNode(common.deprecated)] : [], common.specifiedBy ? [createSpecifiedByDirectiveNode(common.specifiedBy)] : []);
}
function nonEmpty(value) {
return value != null;
}
const buildInDirectives = new Set(graphql_1.specifiedDirectives.map(directive => directive.name));
function isBuiltInDirective(directiveName) {
return buildInDirectives.has(directiveName);
}
function isFederationDirective(name) {
return (name === 'tag' || name === 'link' || name.startsWith('join__') || name.startsWith('link__'));
}
function isFederationEnum(name) {
return name.startsWith('join__') || name.startsWith('link__');
}
function isFederationScalar(name) {
return name.startsWith('join__') || name.startsWith('link__');
}
function schemaCoordinate(paths, nodes) {
let coordinate = '';
for (let i = 0; i < Math.max(paths.length, nodes.length); i++) {
const prop = paths[i];
const current = nodes[i];
if (typeof prop === 'number' && Array.isArray(current)) {
const node = current[prop];
if (coordinate.length > 0) {
coordinate = coordinate + '.' + node.name.value;
}
else {
coordinate = node.name.value;
}
}
}
return coordinate;
}
function stripFederation(supergraph) {
const inaccessible = new Set();
const documentWithoutFederation = (0, graphql_1.visit)(supergraph, (0, graphql_1.visitInParallel)([
{
DirectiveDefinition(node) {
if (isBuiltInDirective(node.name.value) || isFederationDirective(node.name.value)) {
return null;
}
},
Directive(node) {
if (isBuiltInDirective(node.name.value) || isFederationDirective(node.name.value)) {
return null;
}
},
EnumTypeDefinition(node) {
if (isFederationEnum(node.name.value)) {
return null;
}
},
ScalarTypeDefinition(node) {
if (isFederationScalar(node.name.value)) {
return null;
}
},
},
{
Directive(directive, _, __, paths, nodes) {
if (directive.name.value === 'inaccessible') {
inaccessible.add(schemaCoordinate(paths, nodes));
}
},
},
]));
if (inaccessible.size === 0) {
return documentWithoutFederation;
}
function hideByNodeName(node) {
if (inaccessible.has(node.name.value)) {
return null;
}
}
function hideObjectOrInterface(node) {
if (inaccessible.has(node.name.value)) {
return null;
}
const inaccessibleInterfaces = node.interfaces?.filter(i => inaccessible.has(i.name.value));
if (inaccessibleInterfaces?.length) {
return {
...node,
interfaces: node.interfaces?.filter(i => !inaccessible.has(i.name.value)),
};
}
}
function hideField(node, _, __, paths, nodes) {
if (inaccessible.has(schemaCoordinate(paths, nodes) + '.' + node.name.value)) {
return null;
}
if (inaccessible.has(namedTypeFromTypeNode(node.type).name.value)) {
return null;
}
}
return (0, graphql_1.visit)(documentWithoutFederation, {
ObjectTypeDefinition: hideObjectOrInterface,
InterfaceTypeDefinition: hideObjectOrInterface,
InputObjectTypeDefinition: hideByNodeName,
EnumTypeDefinition: hideByNodeName,
UnionTypeDefinition: hideByNodeName,
ScalarTypeDefinition: hideByNodeName,
FieldDefinition: hideField,
InputValueDefinition: hideField,
EnumValueDefinition(node, _, __, paths, nodes) {
if (inaccessible.has(schemaCoordinate(paths, nodes) + '.' + node.name.value)) {
return null;
}
},
});
}
function namedTypeFromTypeNode(type) {
if (type.kind === graphql_1.Kind.NAMED_TYPE) {
return type;
}
if (type.kind === graphql_1.Kind.LIST_TYPE) {
return namedTypeFromTypeNode(type.type);
}
if (type.kind === graphql_1.Kind.NON_NULL_TYPE) {
return namedTypeFromTypeNode(type.type);
}
throw new Error('Unknown type node: ' + type);
}