{"version":3,"file":"UniqueFieldDefinitionNamesRule.js","sourceRoot":"","sources":["../../../src/validation/rules/UniqueFieldDefinitionNamesRule.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,qCAAoC;AAU3D,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,YAAY,GACb,kCAAiC;AA6BlC,MAAM,UAAU,8BAA8B,CAC5C,OAA6B;IAE7B,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IACnC,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3E,MAAM,eAAe,GAAG,IAAI,GAAG,EAAiC,CAAC;IAEjE,OAAO;QACL,yBAAyB,EAAE,oBAAoB;QAC/C,wBAAwB,EAAE,oBAAoB;QAC9C,uBAAuB,EAAE,oBAAoB;QAC7C,sBAAsB,EAAE,oBAAoB;QAC5C,oBAAoB,EAAE,oBAAoB;QAC1C,mBAAmB,EAAE,oBAAoB;KAC1C,CAAC;IAEF,SAAS,oBAAoB,CAAC,IAK7B;QACC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAEjC,IAAI,UAAU,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YACvB,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC;YACvB,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QAErC,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;YAEtC,IAAI,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;gBACnD,OAAO,CAAC,WAAW,CACjB,IAAI,YAAY,CACd,UAAU,QAAQ,IAAI,SAAS,mFAAmF,EAClH,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,CACzB,CACF,CAAC;gBACF,SAAS;YACX,CAAC;YAED,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACjD,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;gBAC3B,OAAO,CAAC,WAAW,CACjB,IAAI,YAAY,CACd,UAAU,QAAQ,IAAI,SAAS,6BAA6B,EAC5D,EAAE,KAAK,EAAE,CAAC,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAC3C,CACF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,IAAsB,EAAE,SAAiB;IACzD,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3E,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;IAC7C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/** @category Validation Rules */\n\nimport { GraphQLError } from '../../error/GraphQLError.ts';\n\nimport type {\n  FieldDefinitionNode,\n  InputValueDefinitionNode,\n  NameNode,\n} from '../../language/ast.ts';\nimport type { ASTVisitor } from '../../language/visitor.ts';\n\nimport type { GraphQLNamedType } from '../../type/definition.ts';\nimport {\n  isInputObjectType,\n  isInterfaceType,\n  isObjectType,\n} from '../../type/definition.ts';\n\nimport type { SDLValidationContext } from '../ValidationContext.ts';\n\n/**\n * Unique field definition names\n *\n * A GraphQL complex type is only valid if all its fields are uniquely named.\n * @param context - The validation context used while checking the document.\n * @returns A visitor that reports validation errors for this rule.\n * @example\n * ```ts\n * import { buildSchema } from 'graphql';\n * import { UniqueFieldDefinitionNamesRule } from 'graphql/validation';\n *\n * const invalidSDL = `\n *   type Query { name: String name: String }\n * `;\n *\n * UniqueFieldDefinitionNamesRule.name; // => 'UniqueFieldDefinitionNamesRule'\n * buildSchema(invalidSDL); // throws an error\n *\n * const validSDL = `\n *   type Query { name: String other: String }\n * `;\n *\n * buildSchema(validSDL); // does not throw\n * ```\n */\nexport function UniqueFieldDefinitionNamesRule(\n  context: SDLValidationContext,\n): ASTVisitor {\n  const schema = context.getSchema();\n  const existingTypeMap = schema ? schema.getTypeMap() : Object.create(null);\n  const knownFieldNames = new Map<string, Map<string, NameNode>>();\n\n  return {\n    InputObjectTypeDefinition: checkFieldUniqueness,\n    InputObjectTypeExtension: checkFieldUniqueness,\n    InterfaceTypeDefinition: checkFieldUniqueness,\n    InterfaceTypeExtension: checkFieldUniqueness,\n    ObjectTypeDefinition: checkFieldUniqueness,\n    ObjectTypeExtension: checkFieldUniqueness,\n  };\n\n  function checkFieldUniqueness(node: {\n    readonly name: NameNode;\n    readonly fields?:\n      | ReadonlyArray<InputValueDefinitionNode | FieldDefinitionNode>\n      | undefined;\n  }) {\n    const typeName = node.name.value;\n\n    let fieldNames = knownFieldNames.get(typeName);\n    if (fieldNames == null) {\n      fieldNames = new Map();\n      knownFieldNames.set(typeName, fieldNames);\n    }\n\n    const fieldNodes = node.fields ?? [];\n\n    for (const fieldDef of fieldNodes) {\n      const fieldName = fieldDef.name.value;\n\n      if (hasField(existingTypeMap[typeName], fieldName)) {\n        context.reportError(\n          new GraphQLError(\n            `Field \"${typeName}.${fieldName}\" already exists in the schema. It cannot also be defined in this type extension.`,\n            { nodes: fieldDef.name },\n          ),\n        );\n        continue;\n      }\n\n      const knownFieldName = fieldNames.get(fieldName);\n      if (knownFieldName != null) {\n        context.reportError(\n          new GraphQLError(\n            `Field \"${typeName}.${fieldName}\" can only be defined once.`,\n            { nodes: [knownFieldName, fieldDef.name] },\n          ),\n        );\n      } else {\n        fieldNames.set(fieldName, fieldDef.name);\n      }\n    }\n\n    return false;\n  }\n}\n\nfunction hasField(type: GraphQLNamedType, fieldName: string): boolean {\n  if (isObjectType(type) || isInterfaceType(type) || isInputObjectType(type)) {\n    return type.getFields()[fieldName] != null;\n  }\n  return false;\n}\n"]}