@graphql-inspector/action
Version:
GraphQL Inspector functionality for GitHub Actions
121 lines (120 loc) • 4.36 kB
JavaScript
import { getLocation, Kind, parse, } from 'graphql';
export function getLocationByPath({ path, source, }) {
const [typeName, ...rest] = path.split('.');
const isDirective = typeName.startsWith('@');
const doc = parse(source);
let resolvedNode = undefined;
for (const definition of doc.definitions) {
if (definition.kind === Kind.OBJECT_TYPE_DEFINITION && definition.name.value === typeName) {
resolvedNode = resolveObjectTypeDefinition(rest, definition);
break;
}
if (isDirective &&
definition.kind === Kind.DIRECTIVE_DEFINITION &&
definition.name.value === typeName.substring(1)) {
resolvedNode = resolveDirectiveDefinition(rest, definition);
break;
}
if (definition.kind === Kind.ENUM_TYPE_DEFINITION && definition.name.value === typeName) {
resolvedNode = resolveEnumTypeDefinition(rest, definition);
break;
}
if (definition.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION &&
definition.name.value === typeName) {
resolvedNode = resolveInputObjectTypeDefinition(rest, definition);
break;
}
if (definition.kind === Kind.INTERFACE_TYPE_DEFINITION && definition.name.value === typeName) {
resolvedNode = resolveInterfaceTypeDefinition(rest, definition);
break;
}
if (definition.kind === Kind.UNION_TYPE_DEFINITION && definition.name.value === typeName) {
resolvedNode = resolveUnionTypeDefinitionNode(rest, definition);
break;
}
if (definition.kind === Kind.SCALAR_TYPE_DEFINITION && definition.name.value === typeName) {
resolvedNode = resolveScalarTypeDefinitionNode(rest, definition);
break;
}
}
return resolveNodeSourceLocation(source, resolvedNode);
}
function resolveScalarTypeDefinitionNode(_path, definition) {
return definition;
}
function resolveUnionTypeDefinitionNode(_path, definition) {
return definition;
}
function resolveArgument(argName, field) {
const arg = field.arguments?.find(a => a.name.value === argName);
return arg || field;
}
function resolveFieldDefinition(path, definition) {
const [fieldName, argName] = path;
const fieldIndex = definition.fields?.findIndex((f) => f.name.value === fieldName);
if (typeof fieldIndex === 'number' && fieldIndex > -1) {
const field = definition.fields[fieldIndex];
if (field.kind !== Kind.INPUT_VALUE_DEFINITION && argName) {
return resolveArgument(argName, field);
}
return field;
}
return definition;
}
function resolveInterfaceTypeDefinition(path, definition) {
const [fieldName, argName] = path;
if (fieldName) {
return resolveFieldDefinition([fieldName, argName], definition);
}
return definition;
}
function resolveInputObjectTypeDefinition(path, definition) {
const [fieldName] = path;
if (fieldName) {
return resolveFieldDefinition([fieldName], definition);
}
return definition;
}
function resolveEnumTypeDefinition(path, definition) {
const [valueName] = path;
if (definition.values && valueName) {
const value = definition.values.find(val => val.name.value === valueName);
if (value) {
return value;
}
}
return definition;
}
function resolveObjectTypeDefinition(path, definition) {
const [fieldName, argName] = path;
if (fieldName) {
return resolveFieldDefinition([fieldName, argName], definition);
}
return definition;
}
function resolveDirectiveDefinition(path, defininition) {
const [argName] = path;
if (defininition.arguments && argName) {
const arg = defininition.arguments.find(arg => arg.name.value === argName);
if (arg) {
return arg;
}
}
return defininition;
}
function resolveNodeSourceLocation(source, node) {
if (!node?.loc) {
return {
line: 1,
column: 1,
};
}
const nodeLocation = getLocation(source, node.loc.start);
if (node.description?.loc) {
return {
line: getLocation(source, node.description.loc.end).line + 1,
column: nodeLocation.column,
};
}
return nodeLocation;
}