1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.UniqueTypeNamesWithFields = exports.existedTypeNameMessage = exports.duplicateTypeNameMessage = void 0;
|
4 | const graphql_1 = require("graphql");
|
5 | const utils_1 = require("../../utils");
|
6 | function duplicateTypeNameMessage(typeName) {
|
7 | return `There can be only one type named "${typeName}".`;
|
8 | }
|
9 | exports.duplicateTypeNameMessage = duplicateTypeNameMessage;
|
10 | function existedTypeNameMessage(typeName) {
|
11 | return `Type "${typeName}" already exists in the schema. It cannot also be defined in this type definition.`;
|
12 | }
|
13 | exports.existedTypeNameMessage = existedTypeNameMessage;
|
14 | function UniqueTypeNamesWithFields(context) {
|
15 | const knownTypes = Object.create(null);
|
16 | const schema = context.getSchema();
|
17 | return {
|
18 | ScalarTypeDefinition: checkTypeName,
|
19 | ObjectTypeDefinition: checkTypeName,
|
20 | InterfaceTypeDefinition: checkTypeName,
|
21 | UnionTypeDefinition: checkTypeName,
|
22 | EnumTypeDefinition: checkTypeName,
|
23 | InputObjectTypeDefinition: checkTypeName,
|
24 | };
|
25 | function checkTypeName(node) {
|
26 | const typeName = node.name.value;
|
27 | const typeFromSchema = schema && schema.getType(typeName);
|
28 | const typeNodeFromSchema = typeFromSchema &&
|
29 | typeFromSchema.astNode;
|
30 | const typeNodeFromDefs = knownTypes[typeName];
|
31 | const duplicateTypeNode = typeNodeFromSchema || typeNodeFromDefs;
|
32 | if (duplicateTypeNode) {
|
33 | const possibleErrors = [];
|
34 | const { kind, fields, fieldArgs } = (0, utils_1.diffTypeNodes)(node, duplicateTypeNode);
|
35 | const fieldsDiff = Object.entries(fields);
|
36 | if (kind.length > 0) {
|
37 | context.reportError((0, utils_1.errorWithCode)('VALUE_TYPE_KIND_MISMATCH', `${(0, utils_1.logServiceAndType)(duplicateTypeNode.serviceName, typeName)}Found kind mismatch on expected value type belonging to services \`${duplicateTypeNode.serviceName}\` and \`${node.serviceName}\`. \`${typeName}\` is defined as both a \`${kind[0]}\` and a \`${kind[1]}\`. In order to define \`${typeName}\` in multiple places, the kinds must be identical.`, [node, duplicateTypeNode]));
|
38 | return;
|
39 | }
|
40 | const typesHaveSameFieldShape = fieldsDiff.length === 0 ||
|
41 | fieldsDiff.every(([fieldName, types]) => {
|
42 | var _a, _b;
|
43 | if (types.length === 2) {
|
44 | const fieldNode = 'fields' in node && ((_a = node.fields) === null || _a === void 0 ? void 0 : _a.find((field) => field.name.value === fieldName));
|
45 | const duplicateFieldNode = 'fields' in duplicateTypeNode && ((_b = duplicateTypeNode.fields) === null || _b === void 0 ? void 0 : _b.find(field => field.name.value === fieldName));
|
46 | possibleErrors.push((0, utils_1.errorWithCode)('VALUE_TYPE_FIELD_TYPE_MISMATCH', `${(0, utils_1.logServiceAndType)(duplicateTypeNode.serviceName, typeName, fieldName)}A field was defined differently in different services. \`${duplicateTypeNode.serviceName}\` and \`${node.serviceName}\` define \`${typeName}.${fieldName}\` as a ${types[1]} and ${types[0]} respectively. In order to define \`${typeName}\` in multiple places, the fields and their types must be identical.`, fieldNode && duplicateFieldNode ? [fieldNode.type, duplicateFieldNode.type] : undefined));
|
47 | return true;
|
48 | }
|
49 | return false;
|
50 | });
|
51 | const fieldArgDiffs = Object.values(fieldArgs);
|
52 | const typesHaveSameInputValuesShape = fieldArgDiffs.length === 0 ||
|
53 | fieldArgDiffs.every((fieldArgDiff) => {
|
54 | const argTypeDiff = Object.entries(fieldArgDiff);
|
55 | return (argTypeDiff.length === 0 ||
|
56 | argTypeDiff.every(([argName, types]) => {
|
57 | if (types.length === 2) {
|
58 | possibleErrors.push((0, utils_1.errorWithCode)('VALUE_TYPE_INPUT_VALUE_MISMATCH', `${(0, utils_1.logServiceAndType)(duplicateTypeNode.serviceName, typeName)}A field's input type (\`${argName}\`) was defined differently in different services. \`${duplicateTypeNode.serviceName}\` and \`${node.serviceName}\` define \`${argName}\` as a ${types[1]} and ${types[0]} respectively. In order to define \`${typeName}\` in multiple places, the input values and their types must be identical.`, [node, duplicateTypeNode]));
|
59 | return true;
|
60 | }
|
61 | return false;
|
62 | }));
|
63 | });
|
64 | if (typesHaveSameFieldShape && typesHaveSameInputValuesShape) {
|
65 | possibleErrors.forEach(error => context.reportError(error));
|
66 | if ((0, utils_1.isTypeNodeAnEntity)(node) || (0, utils_1.isTypeNodeAnEntity)(duplicateTypeNode)) {
|
67 | const entityNode = (0, utils_1.isTypeNodeAnEntity)(duplicateTypeNode)
|
68 | ? duplicateTypeNode
|
69 | : node;
|
70 | context.reportError((0, utils_1.errorWithCode)('VALUE_TYPE_NO_ENTITY', `${(0, utils_1.logServiceAndType)(entityNode.serviceName, typeName)}Value types cannot be entities (using the \`@key\` directive). Please ensure that the \`${typeName}\` type is extended properly or remove the \`@key\` directive if this is not an entity.`, [node, duplicateTypeNode]));
|
71 | }
|
72 | return false;
|
73 | }
|
74 | }
|
75 | if (typeFromSchema) {
|
76 | context.reportError(new graphql_1.GraphQLError(existedTypeNameMessage(typeName), node.name));
|
77 | return;
|
78 | }
|
79 | if (knownTypes[typeName]) {
|
80 | context.reportError(new graphql_1.GraphQLError(duplicateTypeNameMessage(typeName), [
|
81 | knownTypes[typeName],
|
82 | node.name,
|
83 | ]));
|
84 | }
|
85 | else {
|
86 | knownTypes[typeName] = node;
|
87 | }
|
88 | return false;
|
89 | }
|
90 | }
|
91 | exports.UniqueTypeNamesWithFields = UniqueTypeNamesWithFields;
|
92 |
|
\ | No newline at end of file |