UNPKG

@graphql-hive/core

Version:
101 lines (100 loc) 5.04 kB
import { getNamedType, isAbstractType, isInterfaceType, isObjectType, } from 'graphql'; import { HIVE_INTERNAL_TYPENAME } from '../add-hive-typenames.js'; function findFieldAndTypeInSelections(selections, responseName, fragments, currentTypeName = null) { var _a, _b, _c, _d; for (const selection of selections) { switch (selection.kind) { case 'Field': { const nameOrAlias = (_b = (_a = selection.alias) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : selection.name.value; if (nameOrAlias === responseName) { return { fieldNode: selection, typeName: currentTypeName }; } break; } case 'InlineFragment': { const typeConditionName = (_d = (_c = selection.typeCondition) === null || _c === void 0 ? void 0 : _c.name.value) !== null && _d !== void 0 ? _d : currentTypeName; const found = findFieldAndTypeInSelections(selection.selectionSet.selections, responseName, fragments, typeConditionName); if (found) return found; break; } case 'FragmentSpread': { const fragment = fragments[selection.name.value]; if (fragment) { const typeConditionName = fragment.typeCondition.name.value; const found = findFieldAndTypeInSelections(fragment.selectionSet.selections, responseName, fragments, typeConditionName); if (found) return found; } break; } } } return undefined; } export function errorPathToCoordinate(schema, errorPath, document, data) { var _a, _b, _c; let operation; const fragments = {}; for (const def of document.definitions) { if (def.kind === 'OperationDefinition' && !operation) { operation = def; } else if (def.kind === 'FragmentDefinition') { fragments[def.name.value] = def; } } const operationType = (_a = operation === null || operation === void 0 ? void 0 : operation.operation) !== null && _a !== void 0 ? _a : 'query'; const rootTypeMap = { query: schema.getQueryType(), mutation: schema.getMutationType(), subscription: schema.getSubscriptionType(), }; let currentType = rootTypeMap[operationType]; let coordinate = null; let currentSelections = operation === null || operation === void 0 ? void 0 : operation.selectionSet.selections; let currentData = data; for (const segment of errorPath) { if (typeof segment === 'number') { currentData = currentData === null || currentData === void 0 ? void 0 : currentData[segment]; continue; } let nextType = getNamedType(currentType); if (currentData && typeof currentData === 'object' && !Array.isArray(currentData)) { const typeName = (_b = currentData[HIVE_INTERNAL_TYPENAME]) !== null && _b !== void 0 ? _b : currentData.__typename; if (typeof typeName === 'string') { const runtimeType = schema.getType(typeName); if (runtimeType && (isObjectType(runtimeType) || isInterfaceType(runtimeType))) { nextType = runtimeType; } } } currentType = nextType; let astMatch; if (currentSelections) { astMatch = findFieldAndTypeInSelections(currentSelections, segment, fragments); } if (isAbstractType(currentType) && (astMatch === null || astMatch === void 0 ? void 0 : astMatch.typeName)) { const concreteType = schema.getType(astMatch.typeName); if (concreteType && isObjectType(concreteType) && schema.getPossibleTypes(currentType).includes(concreteType)) { currentType = concreteType; } } if (isObjectType(currentType) || isInterfaceType(currentType)) { // Map alias back to original schema field name using our cached astMatch const fieldName = astMatch ? astMatch.fieldNode.name.value : segment; const field = currentType.getFields()[fieldName]; if (!field) { console.warn(`Hive Usage Client: Field '${fieldName}' (segment '${segment}') not found on type '${currentType.name}'. Error ignored.`); return; } coordinate = `${currentType.name}.${field.name}`; currentType = field.type; currentSelections = (_c = astMatch === null || astMatch === void 0 ? void 0 : astMatch.fieldNode.selectionSet) === null || _c === void 0 ? void 0 : _c.selections; currentData = currentData === null || currentData === void 0 ? void 0 : currentData[segment]; } } return coordinate !== null && coordinate !== void 0 ? coordinate : undefined; }