1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.UniqueFieldDefinitionNames = exports.existedFieldDefinitionNameMessage = exports.duplicateFieldDefinitionNameMessage = void 0;
|
4 | const graphql_1 = require("graphql");
|
5 | const utils_1 = require("../../utils");
|
6 | function duplicateFieldDefinitionNameMessage(typeName, fieldName) {
|
7 | return `Field "${typeName}.${fieldName}" can only be defined once.`;
|
8 | }
|
9 | exports.duplicateFieldDefinitionNameMessage = duplicateFieldDefinitionNameMessage;
|
10 | function existedFieldDefinitionNameMessage(typeName, fieldName, serviceName) {
|
11 | return `${(0, utils_1.logServiceAndType)(serviceName, typeName, fieldName)}Field "${typeName}.${fieldName}" already exists in the schema. It cannot also be defined in this type extension. If this is meant to be an external field, add the \`@external\` directive.`;
|
12 | }
|
13 | exports.existedFieldDefinitionNameMessage = existedFieldDefinitionNameMessage;
|
14 | function UniqueFieldDefinitionNames(context) {
|
15 | const schema = context.getSchema();
|
16 | const existingTypeMap = schema
|
17 | ? schema.getTypeMap()
|
18 | : Object.create(null);
|
19 | const knownFieldNames = Object.create(null);
|
20 | const possibleValueTypes = Object.create(null);
|
21 | return {
|
22 | InputObjectTypeExtension: checkFieldUniqueness,
|
23 | InterfaceTypeExtension: checkFieldUniqueness,
|
24 | ObjectTypeExtension: checkFieldUniqueness,
|
25 | InputObjectTypeDefinition: checkFieldUniquenessExcludingValueTypes,
|
26 | InterfaceTypeDefinition: checkFieldUniquenessExcludingValueTypes,
|
27 | ObjectTypeDefinition: checkFieldUniquenessExcludingValueTypes,
|
28 | };
|
29 | function checkFieldUniqueness(node) {
|
30 | var _a;
|
31 | const typeName = node.name.value;
|
32 | if (!knownFieldNames[typeName]) {
|
33 | knownFieldNames[typeName] = Object.create(null);
|
34 | }
|
35 | if (!node.fields) {
|
36 | return false;
|
37 | }
|
38 | const fieldNames = knownFieldNames[typeName];
|
39 | for (const fieldDef of node.fields) {
|
40 | const fieldName = fieldDef.name.value;
|
41 | if (hasField(existingTypeMap[typeName], fieldName)) {
|
42 | const type = existingTypeMap[typeName];
|
43 | context.reportError(new graphql_1.GraphQLError(existedFieldDefinitionNameMessage(typeName, fieldName, (_a = node.serviceName) !== null && _a !== void 0 ? _a : ''), (0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type) || (0, graphql_1.isInputObjectType)(type) ?
|
44 | type.getFields()[fieldName].astNode : undefined));
|
45 | }
|
46 | else if (fieldNames[fieldName]) {
|
47 | context.reportError(new graphql_1.GraphQLError(duplicateFieldDefinitionNameMessage(typeName, fieldName), [fieldNames[fieldName], fieldDef.name]));
|
48 | }
|
49 | else {
|
50 | fieldNames[fieldName] = fieldDef.name;
|
51 | }
|
52 | }
|
53 | return false;
|
54 | }
|
55 | function checkFieldUniquenessExcludingValueTypes(node) {
|
56 | const typeName = node.name.value;
|
57 | const valueTypeFromSchema = existingTypeMap[typeName] &&
|
58 | existingTypeMap[typeName].astNode;
|
59 | const duplicateTypeNode = valueTypeFromSchema || possibleValueTypes[node.name.value];
|
60 | if (duplicateTypeNode) {
|
61 | const { fields, fieldArgs } = (0, utils_1.diffTypeNodes)(node, duplicateTypeNode);
|
62 | if (Object.values(fields).every(diffEntry => diffEntry.length === 2)) {
|
63 | return false;
|
64 | }
|
65 | const fieldArgDiffs = Object.values(fieldArgs);
|
66 | for (const argDiff of fieldArgDiffs) {
|
67 | const argTypes = Object.values(argDiff);
|
68 | if (argTypes.length > 0 &&
|
69 | argTypes.every((diffEntry) => diffEntry.length === 2)) {
|
70 | return false;
|
71 | }
|
72 | }
|
73 | }
|
74 | else {
|
75 | possibleValueTypes[node.name.value] = node;
|
76 | }
|
77 | if (!knownFieldNames[typeName]) {
|
78 | knownFieldNames[typeName] = Object.create(null);
|
79 | }
|
80 | if (!node.fields) {
|
81 | return false;
|
82 | }
|
83 | const fieldNames = knownFieldNames[typeName];
|
84 | for (const fieldDef of node.fields) {
|
85 | const fieldName = fieldDef.name.value;
|
86 | if (hasField(existingTypeMap[typeName], fieldName)) {
|
87 | context.reportError(new graphql_1.GraphQLError(existedFieldDefinitionNameMessage(typeName, fieldName, existingTypeMap[typeName].astNode.serviceName), fieldDef.name));
|
88 | }
|
89 | else if (fieldNames[fieldName]) {
|
90 | context.reportError(new graphql_1.GraphQLError(duplicateFieldDefinitionNameMessage(typeName, fieldName), [fieldNames[fieldName], fieldDef.name]));
|
91 | }
|
92 | else {
|
93 | fieldNames[fieldName] = fieldDef.name;
|
94 | }
|
95 | }
|
96 | return false;
|
97 | }
|
98 | }
|
99 | exports.UniqueFieldDefinitionNames = UniqueFieldDefinitionNames;
|
100 | function hasField(type, fieldName) {
|
101 | if ((0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type) || (0, graphql_1.isInputObjectType)(type)) {
|
102 | return Boolean(type.getFields()[fieldName]);
|
103 | }
|
104 | return false;
|
105 | }
|
106 |
|
\ | No newline at end of file |