'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.DangerousChangeType = exports.BreakingChangeType = undefined; exports.findBreakingChanges = findBreakingChanges; exports.findDangerousChanges = findDangerousChanges; exports.findRemovedTypes = findRemovedTypes; exports.findTypesThatChangedKind = findTypesThatChangedKind; exports.findArgChanges = findArgChanges; exports.findFieldsThatChangedTypeOnObjectOrInterfaceTypes = findFieldsThatChangedTypeOnObjectOrInterfaceTypes; exports.findFieldsThatChangedTypeOnInputObjectTypes = findFieldsThatChangedTypeOnInputObjectTypes; exports.findTypesRemovedFromUnions = findTypesRemovedFromUnions; exports.findTypesAddedToUnions = findTypesAddedToUnions; exports.findValuesRemovedFromEnums = findValuesRemovedFromEnums; exports.findValuesAddedToEnums = findValuesAddedToEnums; exports.findInterfacesRemovedFromObjectTypes = findInterfacesRemovedFromObjectTypes; exports.findInterfacesAddedToObjectTypes = findInterfacesAddedToObjectTypes; exports.findRemovedDirectives = findRemovedDirectives; exports.findRemovedDirectiveArgs = findRemovedDirectiveArgs; exports.findAddedNonNullDirectiveArgs = findAddedNonNullDirectiveArgs; exports.findRemovedLocationsForDirective = findRemovedLocationsForDirective; exports.findRemovedDirectiveLocations = findRemovedDirectiveLocations; var _definition = require('../type/definition'); var _directives = require('../type/directives'); var _schema = require('../type/schema'); var _keyMap = require('../jsutils/keyMap'); var _keyMap2 = _interopRequireDefault(_keyMap); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Copyright (c) 2016-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * strict */ var BreakingChangeType = exports.BreakingChangeType = { FIELD_CHANGED_KIND: 'FIELD_CHANGED_KIND', FIELD_REMOVED: 'FIELD_REMOVED', TYPE_CHANGED_KIND: 'TYPE_CHANGED_KIND', TYPE_REMOVED: 'TYPE_REMOVED', TYPE_REMOVED_FROM_UNION: 'TYPE_REMOVED_FROM_UNION', VALUE_REMOVED_FROM_ENUM: 'VALUE_REMOVED_FROM_ENUM', ARG_REMOVED: 'ARG_REMOVED', ARG_CHANGED_KIND: 'ARG_CHANGED_KIND', NON_NULL_ARG_ADDED: 'NON_NULL_ARG_ADDED', NON_NULL_INPUT_FIELD_ADDED: 'NON_NULL_INPUT_FIELD_ADDED', INTERFACE_REMOVED_FROM_OBJECT: 'INTERFACE_REMOVED_FROM_OBJECT', DIRECTIVE_REMOVED: 'DIRECTIVE_REMOVED', DIRECTIVE_ARG_REMOVED: 'DIRECTIVE_ARG_REMOVED', DIRECTIVE_LOCATION_REMOVED: 'DIRECTIVE_LOCATION_REMOVED', NON_NULL_DIRECTIVE_ARG_ADDED: 'NON_NULL_DIRECTIVE_ARG_ADDED' }; var DangerousChangeType = exports.DangerousChangeType = { ARG_DEFAULT_VALUE_CHANGE: 'ARG_DEFAULT_VALUE_CHANGE', VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM', INTERFACE_ADDED_TO_OBJECT: 'INTERFACE_ADDED_TO_OBJECT', TYPE_ADDED_TO_UNION: 'TYPE_ADDED_TO_UNION', NULLABLE_INPUT_FIELD_ADDED: 'NULLABLE_INPUT_FIELD_ADDED', NULLABLE_ARG_ADDED: 'NULLABLE_ARG_ADDED' }; /** * Given two schemas, returns an Array containing descriptions of all the types * of breaking changes covered by the other functions down below. */ function findBreakingChanges(oldSchema, newSchema) { return [].concat(findRemovedTypes(oldSchema, newSchema), findTypesThatChangedKind(oldSchema, newSchema), findFieldsThatChangedTypeOnObjectOrInterfaceTypes(oldSchema, newSchema), findFieldsThatChangedTypeOnInputObjectTypes(oldSchema, newSchema).breakingChanges, findTypesRemovedFromUnions(oldSchema, newSchema), findValuesRemovedFromEnums(oldSchema, newSchema), findArgChanges(oldSchema, newSchema).breakingChanges, findInterfacesRemovedFromObjectTypes(oldSchema, newSchema), findRemovedDirectives(oldSchema, newSchema), findRemovedDirectiveArgs(oldSchema, newSchema), findAddedNonNullDirectiveArgs(oldSchema, newSchema), findRemovedDirectiveLocations(oldSchema, newSchema)); } /** * Given two schemas, returns an Array containing descriptions of all the types * of potentially dangerous changes covered by the other functions down below. */ function findDangerousChanges(oldSchema, newSchema) { return [].concat(findArgChanges(oldSchema, newSchema).dangerousChanges, findValuesAddedToEnums(oldSchema, newSchema), findInterfacesAddedToObjectTypes(oldSchema, newSchema), findTypesAddedToUnions(oldSchema, newSchema), findFieldsThatChangedTypeOnInputObjectTypes(oldSchema, newSchema).dangerousChanges); } /** * Given two schemas, returns an Array containing descriptions of any breaking * changes in the newSchema related to removing an entire type. */ function findRemovedTypes(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var breakingChanges = []; Object.keys(oldTypeMap).forEach(function (typeName) { if (!newTypeMap[typeName]) { breakingChanges.push({ type: BreakingChangeType.TYPE_REMOVED, description: typeName + ' was removed.' }); } }); return breakingChanges; } /** * Given two schemas, returns an Array containing descriptions of any breaking * changes in the newSchema related to changing the type of a type. */ function findTypesThatChangedKind(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var breakingChanges = []; Object.keys(oldTypeMap).forEach(function (typeName) { if (!newTypeMap[typeName]) { return; } var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (oldType.constructor !== newType.constructor) { breakingChanges.push({ type: BreakingChangeType.TYPE_CHANGED_KIND, description: typeName + ' changed from ' + (typeKindName(oldType) + ' to ' + typeKindName(newType) + '.') }); } }); return breakingChanges; } /** * Given two schemas, returns an Array containing descriptions of any * breaking or dangerous changes in the newSchema related to arguments * (such as removal or change of type of an argument, or a change in an * argument's default value). */ function findArgChanges(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var breakingChanges = []; var dangerousChanges = []; Object.keys(oldTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!((0, _definition.isObjectType)(oldType) || (0, _definition.isInterfaceType)(oldType)) || !((0, _definition.isObjectType)(newType) || (0, _definition.isInterfaceType)(newType)) || newType.constructor !== oldType.constructor) { return; } var oldTypeFields = oldType.getFields(); var newTypeFields = newType.getFields(); Object.keys(oldTypeFields).forEach(function (fieldName) { if (!newTypeFields[fieldName]) { return; } oldTypeFields[fieldName].args.forEach(function (oldArgDef) { var newArgs = newTypeFields[fieldName].args; var newArgDef = newArgs.find(function (arg) { return arg.name === oldArgDef.name; }); // Arg not present if (!newArgDef) { breakingChanges.push({ type: BreakingChangeType.ARG_REMOVED, description: oldType.name + '.' + fieldName + ' arg ' + (oldArgDef.name + ' was removed') }); } else { var isSafe = isChangeSafeForInputObjectFieldOrFieldArg(oldArgDef.type, newArgDef.type); if (!isSafe) { breakingChanges.push({ type: BreakingChangeType.ARG_CHANGED_KIND, description: oldType.name + '.' + fieldName + ' arg ' + (oldArgDef.name + ' has changed type from ') + (oldArgDef.type.toString() + ' to ' + newArgDef.type.toString()) }); } else if (oldArgDef.defaultValue !== undefined && oldArgDef.defaultValue !== newArgDef.defaultValue) { dangerousChanges.push({ type: DangerousChangeType.ARG_DEFAULT_VALUE_CHANGE, description: oldType.name + '.' + fieldName + ' arg ' + (oldArgDef.name + ' has changed defaultValue') }); } } }); // Check if a non-null arg was added to the field newTypeFields[fieldName].args.forEach(function (newArgDef) { var oldArgs = oldTypeFields[fieldName].args; var oldArgDef = oldArgs.find(function (arg) { return arg.name === newArgDef.name; }); if (!oldArgDef) { if ((0, _definition.isNonNullType)(newArgDef.type)) { breakingChanges.push({ type: BreakingChangeType.NON_NULL_ARG_ADDED, description: 'A non-null arg ' + newArgDef.name + ' on ' + (newType.name + '.' + fieldName + ' was added') }); } else { dangerousChanges.push({ type: DangerousChangeType.NULLABLE_ARG_ADDED, description: 'A nullable arg ' + newArgDef.name + ' on ' + (newType.name + '.' + fieldName + ' was added') }); } } }); }); }); return { breakingChanges: breakingChanges, dangerousChanges: dangerousChanges }; } function typeKindName(type) { if ((0, _definition.isScalarType)(type)) { return 'a Scalar type'; } if ((0, _definition.isObjectType)(type)) { return 'an Object type'; } if ((0, _definition.isInterfaceType)(type)) { return 'an Interface type'; } if ((0, _definition.isUnionType)(type)) { return 'a Union type'; } if ((0, _definition.isEnumType)(type)) { return 'an Enum type'; } if ((0, _definition.isInputObjectType)(type)) { return 'an Input type'; } throw new TypeError('Unknown type ' + type.constructor.name); } function findFieldsThatChangedTypeOnObjectOrInterfaceTypes(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var breakingChanges = []; Object.keys(oldTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!((0, _definition.isObjectType)(oldType) || (0, _definition.isInterfaceType)(oldType)) || !((0, _definition.isObjectType)(newType) || (0, _definition.isInterfaceType)(newType)) || newType.constructor !== oldType.constructor) { return; } var oldTypeFieldsDef = oldType.getFields(); var newTypeFieldsDef = newType.getFields(); Object.keys(oldTypeFieldsDef).forEach(function (fieldName) { // Check if the field is missing on the type in the new schema. if (!(fieldName in newTypeFieldsDef)) { breakingChanges.push({ type: BreakingChangeType.FIELD_REMOVED, description: typeName + '.' + fieldName + ' was removed.' }); } else { var oldFieldType = oldTypeFieldsDef[fieldName].type; var newFieldType = newTypeFieldsDef[fieldName].type; var isSafe = isChangeSafeForObjectOrInterfaceField(oldFieldType, newFieldType); if (!isSafe) { var oldFieldTypeString = (0, _definition.isNamedType)(oldFieldType) ? oldFieldType.name : oldFieldType.toString(); var newFieldTypeString = (0, _definition.isNamedType)(newFieldType) ? newFieldType.name : newFieldType.toString(); breakingChanges.push({ type: BreakingChangeType.FIELD_CHANGED_KIND, description: typeName + '.' + fieldName + ' changed type from ' + (oldFieldTypeString + ' to ' + newFieldTypeString + '.') }); } } }); }); return breakingChanges; } function findFieldsThatChangedTypeOnInputObjectTypes(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var breakingChanges = []; var dangerousChanges = []; Object.keys(oldTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!(0, _definition.isInputObjectType)(oldType) || !(0, _definition.isInputObjectType)(newType)) { return; } var oldTypeFieldsDef = oldType.getFields(); var newTypeFieldsDef = newType.getFields(); Object.keys(oldTypeFieldsDef).forEach(function (fieldName) { // Check if the field is missing on the type in the new schema. if (!(fieldName in newTypeFieldsDef)) { breakingChanges.push({ type: BreakingChangeType.FIELD_REMOVED, description: typeName + '.' + fieldName + ' was removed.' }); } else { var oldFieldType = oldTypeFieldsDef[fieldName].type; var newFieldType = newTypeFieldsDef[fieldName].type; var isSafe = isChangeSafeForInputObjectFieldOrFieldArg(oldFieldType, newFieldType); if (!isSafe) { var oldFieldTypeString = (0, _definition.isNamedType)(oldFieldType) ? oldFieldType.name : oldFieldType.toString(); var newFieldTypeString = (0, _definition.isNamedType)(newFieldType) ? newFieldType.name : newFieldType.toString(); breakingChanges.push({ type: BreakingChangeType.FIELD_CHANGED_KIND, description: typeName + '.' + fieldName + ' changed type from ' + (oldFieldTypeString + ' to ' + newFieldTypeString + '.') }); } } }); // Check if a field was added to the input object type Object.keys(newTypeFieldsDef).forEach(function (fieldName) { if (!(fieldName in oldTypeFieldsDef)) { if ((0, _definition.isNonNullType)(newTypeFieldsDef[fieldName].type)) { breakingChanges.push({ type: BreakingChangeType.NON_NULL_INPUT_FIELD_ADDED, description: 'A non-null field ' + fieldName + ' on ' + ('input type ' + newType.name + ' was added.') }); } else { dangerousChanges.push({ type: DangerousChangeType.NULLABLE_INPUT_FIELD_ADDED, description: 'A nullable field ' + fieldName + ' on ' + ('input type ' + newType.name + ' was added.') }); } } }); }); return { breakingChanges: breakingChanges, dangerousChanges: dangerousChanges }; } function isChangeSafeForObjectOrInterfaceField(oldType, newType) { if ((0, _definition.isNamedType)(oldType)) { return ( // if they're both named types, see if their names are equivalent (0, _definition.isNamedType)(newType) && oldType.name === newType.name || // moving from nullable to non-null of the same underlying type is safe (0, _definition.isNonNullType)(newType) && isChangeSafeForObjectOrInterfaceField(oldType, newType.ofType) ); } else if ((0, _definition.isListType)(oldType)) { return ( // if they're both lists, make sure the underlying types are compatible (0, _definition.isListType)(newType) && isChangeSafeForObjectOrInterfaceField(oldType.ofType, newType.ofType) || // moving from nullable to non-null of the same underlying type is safe (0, _definition.isNonNullType)(newType) && isChangeSafeForObjectOrInterfaceField(oldType, newType.ofType) ); } else if ((0, _definition.isNonNullType)(oldType)) { // if they're both non-null, make sure the underlying types are compatible return (0, _definition.isNonNullType)(newType) && isChangeSafeForObjectOrInterfaceField(oldType.ofType, newType.ofType); } return false; } function isChangeSafeForInputObjectFieldOrFieldArg(oldType, newType) { if ((0, _definition.isNamedType)(oldType)) { // if they're both named types, see if their names are equivalent return (0, _definition.isNamedType)(newType) && oldType.name === newType.name; } else if ((0, _definition.isListType)(oldType)) { // if they're both lists, make sure the underlying types are compatible return (0, _definition.isListType)(newType) && isChangeSafeForInputObjectFieldOrFieldArg(oldType.ofType, newType.ofType); } else if ((0, _definition.isNonNullType)(oldType)) { return ( // if they're both non-null, make sure the underlying types are // compatible (0, _definition.isNonNullType)(newType) && isChangeSafeForInputObjectFieldOrFieldArg(oldType.ofType, newType.ofType) || // moving from non-null to nullable of the same underlying type is safe !(0, _definition.isNonNullType)(newType) && isChangeSafeForInputObjectFieldOrFieldArg(oldType.ofType, newType) ); } return false; } /** * Given two schemas, returns an Array containing descriptions of any breaking * changes in the newSchema related to removing types from a union type. */ function findTypesRemovedFromUnions(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var typesRemovedFromUnion = []; Object.keys(oldTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!(0, _definition.isUnionType)(oldType) || !(0, _definition.isUnionType)(newType)) { return; } var typeNamesInNewUnion = Object.create(null); newType.getTypes().forEach(function (type) { typeNamesInNewUnion[type.name] = true; }); oldType.getTypes().forEach(function (type) { if (!typeNamesInNewUnion[type.name]) { typesRemovedFromUnion.push({ type: BreakingChangeType.TYPE_REMOVED_FROM_UNION, description: type.name + ' was removed from union type ' + typeName + '.' }); } }); }); return typesRemovedFromUnion; } /** * Given two schemas, returns an Array containing descriptions of any dangerous * changes in the newSchema related to adding types to a union type. */ function findTypesAddedToUnions(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var typesAddedToUnion = []; Object.keys(newTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!(0, _definition.isUnionType)(oldType) || !(0, _definition.isUnionType)(newType)) { return; } var typeNamesInOldUnion = Object.create(null); oldType.getTypes().forEach(function (type) { typeNamesInOldUnion[type.name] = true; }); newType.getTypes().forEach(function (type) { if (!typeNamesInOldUnion[type.name]) { typesAddedToUnion.push({ type: DangerousChangeType.TYPE_ADDED_TO_UNION, description: type.name + ' was added to union type ' + typeName + '.' }); } }); }); return typesAddedToUnion; } /** * Given two schemas, returns an Array containing descriptions of any breaking * changes in the newSchema related to removing values from an enum type. */ function findValuesRemovedFromEnums(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var valuesRemovedFromEnums = []; Object.keys(oldTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!(0, _definition.isEnumType)(oldType) || !(0, _definition.isEnumType)(newType)) { return; } var valuesInNewEnum = Object.create(null); newType.getValues().forEach(function (value) { valuesInNewEnum[value.name] = true; }); oldType.getValues().forEach(function (value) { if (!valuesInNewEnum[value.name]) { valuesRemovedFromEnums.push({ type: BreakingChangeType.VALUE_REMOVED_FROM_ENUM, description: value.name + ' was removed from enum type ' + typeName + '.' }); } }); }); return valuesRemovedFromEnums; } /** * Given two schemas, returns an Array containing descriptions of any dangerous * changes in the newSchema related to adding values to an enum type. */ function findValuesAddedToEnums(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var valuesAddedToEnums = []; Object.keys(oldTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!(0, _definition.isEnumType)(oldType) || !(0, _definition.isEnumType)(newType)) { return; } var valuesInOldEnum = Object.create(null); oldType.getValues().forEach(function (value) { valuesInOldEnum[value.name] = true; }); newType.getValues().forEach(function (value) { if (!valuesInOldEnum[value.name]) { valuesAddedToEnums.push({ type: DangerousChangeType.VALUE_ADDED_TO_ENUM, description: value.name + ' was added to enum type ' + typeName + '.' }); } }); }); return valuesAddedToEnums; } function findInterfacesRemovedFromObjectTypes(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var breakingChanges = []; Object.keys(oldTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!(0, _definition.isObjectType)(oldType) || !(0, _definition.isObjectType)(newType)) { return; } var oldInterfaces = oldType.getInterfaces(); var newInterfaces = newType.getInterfaces(); oldInterfaces.forEach(function (oldInterface) { if (!newInterfaces.some(function (int) { return int.name === oldInterface.name; })) { breakingChanges.push({ type: BreakingChangeType.INTERFACE_REMOVED_FROM_OBJECT, description: typeName + ' no longer implements interface ' + (oldInterface.name + '.') }); } }); }); return breakingChanges; } function findInterfacesAddedToObjectTypes(oldSchema, newSchema) { var oldTypeMap = oldSchema.getTypeMap(); var newTypeMap = newSchema.getTypeMap(); var interfacesAddedToObjectTypes = []; Object.keys(newTypeMap).forEach(function (typeName) { var oldType = oldTypeMap[typeName]; var newType = newTypeMap[typeName]; if (!(0, _definition.isObjectType)(oldType) || !(0, _definition.isObjectType)(newType)) { return; } var oldInterfaces = oldType.getInterfaces(); var newInterfaces = newType.getInterfaces(); newInterfaces.forEach(function (newInterface) { if (!oldInterfaces.some(function (int) { return int.name === newInterface.name; })) { interfacesAddedToObjectTypes.push({ type: DangerousChangeType.INTERFACE_ADDED_TO_OBJECT, description: newInterface.name + ' added to interfaces implemented ' + ('by ' + typeName + '.') }); } }); }); return interfacesAddedToObjectTypes; } function findRemovedDirectives(oldSchema, newSchema) { var removedDirectives = []; var newSchemaDirectiveMap = getDirectiveMapForSchema(newSchema); oldSchema.getDirectives().forEach(function (directive) { if (!newSchemaDirectiveMap[directive.name]) { removedDirectives.push({ type: BreakingChangeType.DIRECTIVE_REMOVED, description: directive.name + ' was removed' }); } }); return removedDirectives; } function findRemovedArgsForDirective(oldDirective, newDirective) { var removedArgs = []; var newArgMap = getArgumentMapForDirective(newDirective); oldDirective.args.forEach(function (arg) { if (!newArgMap[arg.name]) { removedArgs.push(arg); } }); return removedArgs; } function findRemovedDirectiveArgs(oldSchema, newSchema) { var removedDirectiveArgs = []; var oldSchemaDirectiveMap = getDirectiveMapForSchema(oldSchema); newSchema.getDirectives().forEach(function (newDirective) { var oldDirective = oldSchemaDirectiveMap[newDirective.name]; if (!oldDirective) { return; } findRemovedArgsForDirective(oldDirective, newDirective).forEach(function (arg) { removedDirectiveArgs.push({ type: BreakingChangeType.DIRECTIVE_ARG_REMOVED, description: arg.name + ' was removed from ' + newDirective.name }); }); }); return removedDirectiveArgs; } function findAddedArgsForDirective(oldDirective, newDirective) { var addedArgs = []; var oldArgMap = getArgumentMapForDirective(oldDirective); newDirective.args.forEach(function (arg) { if (!oldArgMap[arg.name]) { addedArgs.push(arg); } }); return addedArgs; } function findAddedNonNullDirectiveArgs(oldSchema, newSchema) { var addedNonNullableArgs = []; var oldSchemaDirectiveMap = getDirectiveMapForSchema(oldSchema); newSchema.getDirectives().forEach(function (newDirective) { var oldDirective = oldSchemaDirectiveMap[newDirective.name]; if (!oldDirective) { return; } findAddedArgsForDirective(oldDirective, newDirective).forEach(function (arg) { if (!(0, _definition.isNonNullType)(arg.type)) { return; } addedNonNullableArgs.push({ type: BreakingChangeType.NON_NULL_DIRECTIVE_ARG_ADDED, description: 'A non-null arg ' + arg.name + ' on directive ' + (newDirective.name + ' was added') }); }); }); return addedNonNullableArgs; } function findRemovedLocationsForDirective(oldDirective, newDirective) { var removedLocations = []; var newLocationSet = new Set(newDirective.locations); oldDirective.locations.forEach(function (oldLocation) { if (!newLocationSet.has(oldLocation)) { removedLocations.push(oldLocation); } }); return removedLocations; } function findRemovedDirectiveLocations(oldSchema, newSchema) { var removedLocations = []; var oldSchemaDirectiveMap = getDirectiveMapForSchema(oldSchema); newSchema.getDirectives().forEach(function (newDirective) { var oldDirective = oldSchemaDirectiveMap[newDirective.name]; if (!oldDirective) { return; } findRemovedLocationsForDirective(oldDirective, newDirective).forEach(function (location) { removedLocations.push({ type: BreakingChangeType.DIRECTIVE_LOCATION_REMOVED, description: location + ' was removed from ' + newDirective.name }); }); }); return removedLocations; } function getDirectiveMapForSchema(schema) { return (0, _keyMap2.default)(schema.getDirectives(), function (dir) { return dir.name; }); } function getArgumentMapForDirective(directive) { return (0, _keyMap2.default)(directive.args, function (arg) { return arg.name; }); }