mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-29 08:26:02 +03:00
initial porting
This commit is contained in:
parent
eaadae4a5b
commit
7aebf2dbf7
609
src/Utils/FindBreakingChanges.php
Normal file
609
src/Utils/FindBreakingChanges.php
Normal file
@ -0,0 +1,609 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Utility for finding breaking/dangerous changes between two schemas.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace GraphQL\Utils;
|
||||||
|
|
||||||
|
|
||||||
|
class FindBreakingChanges {
|
||||||
|
|
||||||
|
const BREAKING_CHANGE_FIELD_CHANGED = 'FIELD_CHANGED_KIND';
|
||||||
|
const BREAKING_CHANGE_FIELD_REMOVED = 'FIELD_REMOVED';
|
||||||
|
const BREAKING_CHANGE_TYPE_CHANGED = 'TYPE_CHANGED_KIND';
|
||||||
|
const BREAKING_CHANGE_TYPE_REMOVED = 'TYPE_REMOVED';
|
||||||
|
const BREAKING_CHANGE_TYPE_REMOVED_FROM_UNION = 'TYPE_REMOVED_FROM_UNION';
|
||||||
|
const BREAKING_CHANGE_VALUE_REMOVED_FROM_ENUM = 'VALUE_REMOVED_FROM_ENUM';
|
||||||
|
const BREAKING_CHANGE_ARG_REMOVED = 'ARG_REMOVED';
|
||||||
|
const BREAKING_CHANGE_ARG_CHANGED = 'ARG_CHANGED_KIND';
|
||||||
|
const BREAKING_CHANGE_NON_NULL_ARG_ADDED = 'NON_NULL_ARG_ADDED';
|
||||||
|
const BREAKING_CHANGE_NON_NULL_INPUT_FIELD_ADDED = 'NON_NULL_INPUT_FIELD_ADDED';
|
||||||
|
const BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT = 'INTERFACE_REMOVED_FROM_OBJECT';
|
||||||
|
/*
|
||||||
|
export const DangerousChangeType = {
|
||||||
|
ARG_DEFAULT_VALUE_CHANGE: 'ARG_DEFAULT_VALUE_CHANGE',
|
||||||
|
VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM',
|
||||||
|
TYPE_ADDED_TO_UNION: 'TYPE_ADDED_TO_UNION',
|
||||||
|
};*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given two schemas, returns an Array containing descriptions of all the types
|
||||||
|
* of breaking changes covered by the other functions down below.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function findBreakingChanges(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
return [
|
||||||
|
/*...findRemovedTypes(oldSchema, newSchema),
|
||||||
|
...findTypesThatChangedKind(oldSchema, newSchema),
|
||||||
|
...findFieldsThatChangedType(oldSchema, newSchema),
|
||||||
|
...findTypesRemovedFromUnions(oldSchema, newSchema),
|
||||||
|
...findValuesRemovedFromEnums(oldSchema, newSchema),
|
||||||
|
...findArgChanges(oldSchema, newSchema).breakingChanges,
|
||||||
|
...findInterfacesRemovedFromObjectTypes(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.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function findDangerousChanges(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
return [
|
||||||
|
/* ...findArgChanges(oldSchema, newSchema).dangerousChanges,
|
||||||
|
...findValuesAddedToEnums(oldSchema, newSchema),
|
||||||
|
...findTypesAddedToUnions(oldSchema, newSchema)
|
||||||
|
*/
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given two schemas, returns an Array containing descriptions of any breaking
|
||||||
|
* changes in the newSchema related to removing an entire type.
|
||||||
|
*/
|
||||||
|
public function findRemovedTypes(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/*const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const breakingChanges = [];
|
||||||
|
Object.keys(oldTypeMap).forEach(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.
|
||||||
|
*/
|
||||||
|
public function findTypesThatChangedKind(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/*const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const breakingChanges = [];
|
||||||
|
Object.keys(oldTypeMap).forEach(typeName => {
|
||||||
|
if (!newTypeMap[typeName]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (!(oldType instanceof 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).
|
||||||
|
*/
|
||||||
|
public function findArgChanges(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/* const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const breakingChanges = [];
|
||||||
|
const dangerousChanges = [];
|
||||||
|
|
||||||
|
Object.keys(oldTypeMap).forEach(typeName => {
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (
|
||||||
|
!(oldType instanceof GraphQLObjectType ||
|
||||||
|
oldType instanceof GraphQLInterfaceType) ||
|
||||||
|
!(newType instanceof oldType.constructor)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldTypeFields: GraphQLFieldMap<*, *> = oldType.getFields();
|
||||||
|
const newTypeFields: GraphQLFieldMap<*, *> = newType.getFields();
|
||||||
|
|
||||||
|
Object.keys(oldTypeFields).forEach(fieldName => {
|
||||||
|
if (!newTypeFields[fieldName]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldTypeFields[fieldName].args.forEach(oldArgDef => {
|
||||||
|
const newArgs = newTypeFields[fieldName].args;
|
||||||
|
const newArgDef = newArgs.find(
|
||||||
|
arg => 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 {
|
||||||
|
const 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(newArgDef => {
|
||||||
|
const oldArgs = oldTypeFields[fieldName].args;
|
||||||
|
const oldArgDef = oldArgs.find(
|
||||||
|
arg => arg.name === newArgDef.name
|
||||||
|
);
|
||||||
|
if (!oldArgDef && newArgDef.type instanceof GraphQLNonNull) {
|
||||||
|
breakingChanges.push({
|
||||||
|
type: BreakingChangeType.NON_NULL_ARG_ADDED,
|
||||||
|
description: `A non-null arg ${newArgDef.name} on ` +
|
||||||
|
`${newType.name}.${fieldName} was added`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
breakingChanges,
|
||||||
|
dangerousChanges,
|
||||||
|
};*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function typeKindName($type) {
|
||||||
|
/* if (type instanceof GraphQLScalarType) {
|
||||||
|
return 'a Scalar type';
|
||||||
|
}
|
||||||
|
if (type instanceof GraphQLObjectType) {
|
||||||
|
return 'an Object type';
|
||||||
|
}
|
||||||
|
if (type instanceof GraphQLInterfaceType) {
|
||||||
|
return 'an Interface type';
|
||||||
|
}
|
||||||
|
if (type instanceof GraphQLUnionType) {
|
||||||
|
return 'a Union type';
|
||||||
|
}
|
||||||
|
if (type instanceof GraphQLEnumType) {
|
||||||
|
return 'an Enum type';
|
||||||
|
}
|
||||||
|
if (type instanceof GraphQLInputObjectType) {
|
||||||
|
return 'an Input type';
|
||||||
|
}
|
||||||
|
throw new TypeError('Unknown type ' + type.constructor.name);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given two schemas, returns an Array containing descriptions of any breaking
|
||||||
|
* changes in the newSchema related to the fields on a type. This includes if
|
||||||
|
* a field has been removed from a type, if a field has changed type, or if
|
||||||
|
* a non-null field is added to an input type.
|
||||||
|
*/
|
||||||
|
public static function findFieldsThatChangedType(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/*return [
|
||||||
|
...findFieldsThatChangedTypeOnObjectOrInterfaceTypes(oldSchema, newSchema),
|
||||||
|
...findFieldsThatChangedTypeOnInputObjectTypes(oldSchema, newSchema),
|
||||||
|
];*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function findFieldsThatChangedTypeOnObjectOrInterfaceTypes(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/*const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const breakingFieldChanges = [];
|
||||||
|
Object.keys(oldTypeMap).forEach(typeName => {
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (
|
||||||
|
!(oldType instanceof GraphQLObjectType ||
|
||||||
|
oldType instanceof GraphQLInterfaceType) ||
|
||||||
|
!(newType instanceof oldType.constructor)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldTypeFieldsDef = oldType.getFields();
|
||||||
|
const newTypeFieldsDef = newType.getFields();
|
||||||
|
Object.keys(oldTypeFieldsDef).forEach(fieldName => {
|
||||||
|
// Check if the field is missing on the type in the new schema.
|
||||||
|
if (!(fieldName in newTypeFieldsDef)) {
|
||||||
|
breakingFieldChanges.push({
|
||||||
|
type: BreakingChangeType.FIELD_REMOVED,
|
||||||
|
description: `${typeName}.${fieldName} was removed.`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const oldFieldType = oldTypeFieldsDef[fieldName].type;
|
||||||
|
const newFieldType = newTypeFieldsDef[fieldName].type;
|
||||||
|
const isSafe =
|
||||||
|
isChangeSafeForObjectOrInterfaceField(oldFieldType, newFieldType);
|
||||||
|
if (!isSafe) {
|
||||||
|
const oldFieldTypeString = isNamedType(oldFieldType) ?
|
||||||
|
oldFieldType.name :
|
||||||
|
oldFieldType.toString();
|
||||||
|
const newFieldTypeString = isNamedType(newFieldType) ?
|
||||||
|
newFieldType.name :
|
||||||
|
newFieldType.toString();
|
||||||
|
breakingFieldChanges.push({
|
||||||
|
type: BreakingChangeType.FIELD_CHANGED_KIND,
|
||||||
|
description: `${typeName}.${fieldName} changed type from ` +
|
||||||
|
`${oldFieldTypeString} to ${newFieldTypeString}.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return breakingFieldChanges;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function findFieldsThatChangedTypeOnInputObjectTypes(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/* const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const breakingFieldChanges = [];
|
||||||
|
Object.keys(oldTypeMap).forEach(typeName => {
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (
|
||||||
|
!(oldType instanceof GraphQLInputObjectType) ||
|
||||||
|
!(newType instanceof GraphQLInputObjectType)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldTypeFieldsDef = oldType.getFields();
|
||||||
|
const newTypeFieldsDef = newType.getFields();
|
||||||
|
Object.keys(oldTypeFieldsDef).forEach(fieldName => {
|
||||||
|
// Check if the field is missing on the type in the new schema.
|
||||||
|
if (!(fieldName in newTypeFieldsDef)) {
|
||||||
|
breakingFieldChanges.push({
|
||||||
|
type: BreakingChangeType.FIELD_REMOVED,
|
||||||
|
description: `${typeName}.${fieldName} was removed.`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const oldFieldType = oldTypeFieldsDef[fieldName].type;
|
||||||
|
const newFieldType = newTypeFieldsDef[fieldName].type;
|
||||||
|
|
||||||
|
const isSafe =
|
||||||
|
isChangeSafeForInputObjectFieldOrFieldArg(oldFieldType, newFieldType);
|
||||||
|
if (!isSafe) {
|
||||||
|
const oldFieldTypeString = isNamedType(oldFieldType) ?
|
||||||
|
oldFieldType.name :
|
||||||
|
oldFieldType.toString();
|
||||||
|
const newFieldTypeString = isNamedType(newFieldType) ?
|
||||||
|
newFieldType.name :
|
||||||
|
newFieldType.toString();
|
||||||
|
breakingFieldChanges.push({
|
||||||
|
type: BreakingChangeType.FIELD_CHANGED_KIND,
|
||||||
|
description: `${typeName}.${fieldName} changed type from ` +
|
||||||
|
`${oldFieldTypeString} to ${newFieldTypeString}.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Check if a non-null field was added to the input object type
|
||||||
|
Object.keys(newTypeFieldsDef).forEach(fieldName => {
|
||||||
|
if (
|
||||||
|
!(fieldName in oldTypeFieldsDef) &&
|
||||||
|
newTypeFieldsDef[fieldName].type instanceof GraphQLNonNull
|
||||||
|
) {
|
||||||
|
breakingFieldChanges.push({
|
||||||
|
type: BreakingChangeType.NON_NULL_INPUT_FIELD_ADDED,
|
||||||
|
description: `A non-null field ${fieldName} on ` +
|
||||||
|
`input type ${newType.name} was added.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return breakingFieldChanges;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function isChangeSafeForObjectOrInterfaceField(
|
||||||
|
$oldType, $newType
|
||||||
|
) {
|
||||||
|
/*if (isNamedType(oldType)) {
|
||||||
|
return (
|
||||||
|
// if they're both named types, see if their names are equivalent
|
||||||
|
isNamedType(newType) && oldType.name === newType.name
|
||||||
|
) ||
|
||||||
|
(
|
||||||
|
// moving from nullable to non-null of the same underlying type is safe
|
||||||
|
newType instanceof GraphQLNonNull &&
|
||||||
|
isChangeSafeForObjectOrInterfaceField(
|
||||||
|
oldType,
|
||||||
|
newType.ofType,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else if (oldType instanceof GraphQLList) {
|
||||||
|
return (
|
||||||
|
// if they're both lists, make sure the underlying types are compatible
|
||||||
|
newType instanceof GraphQLList &&
|
||||||
|
isChangeSafeForObjectOrInterfaceField(
|
||||||
|
oldType.ofType,
|
||||||
|
newType.ofType,
|
||||||
|
)
|
||||||
|
) ||
|
||||||
|
(
|
||||||
|
// moving from nullable to non-null of the same underlying type is safe
|
||||||
|
newType instanceof GraphQLNonNull &&
|
||||||
|
isChangeSafeForObjectOrInterfaceField(
|
||||||
|
oldType,
|
||||||
|
newType.ofType,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else if (oldType instanceof GraphQLNonNull) {
|
||||||
|
// if they're both non-null, make sure the underlying types are compatible
|
||||||
|
return newType instanceof GraphQLNonNull &&
|
||||||
|
isChangeSafeForObjectOrInterfaceField(
|
||||||
|
oldType.ofType,
|
||||||
|
newType.ofType,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function isChangeSafeForInputObjectFieldOrFieldArg(
|
||||||
|
$oldType, $newType
|
||||||
|
) {
|
||||||
|
/* if (isNamedType(oldType)) {
|
||||||
|
// if they're both named types, see if their names are equivalent
|
||||||
|
return isNamedType(newType) && oldType.name === newType.name;
|
||||||
|
} else if (oldType instanceof GraphQLList) {
|
||||||
|
// if they're both lists, make sure the underlying types are compatible
|
||||||
|
return newType instanceof GraphQLList &&
|
||||||
|
isChangeSafeForInputObjectFieldOrFieldArg(
|
||||||
|
oldType.ofType,
|
||||||
|
newType.ofType,
|
||||||
|
);
|
||||||
|
} else if (oldType instanceof GraphQLNonNull) {
|
||||||
|
return (
|
||||||
|
// if they're both non-null, make sure the underlying types are
|
||||||
|
// compatible
|
||||||
|
newType instanceof GraphQLNonNull &&
|
||||||
|
isChangeSafeForInputObjectFieldOrFieldArg(
|
||||||
|
oldType.ofType,
|
||||||
|
newType.ofType,
|
||||||
|
)
|
||||||
|
) ||
|
||||||
|
(
|
||||||
|
// moving from non-null to nullable of the same underlying type is safe
|
||||||
|
!(newType instanceof GraphQLNonNull) &&
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
public static function findTypesRemovedFromUnions(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/* const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const typesRemovedFromUnion = [];
|
||||||
|
Object.keys(oldTypeMap).forEach(typeName => {
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (!(oldType instanceof GraphQLUnionType) ||
|
||||||
|
!(newType instanceof GraphQLUnionType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const typeNamesInNewUnion = Object.create(null);
|
||||||
|
newType.getTypes().forEach(type => {
|
||||||
|
typeNamesInNewUnion[type.name] = true;
|
||||||
|
});
|
||||||
|
oldType.getTypes().forEach(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.
|
||||||
|
*/
|
||||||
|
public static function findTypesAddedToUnions(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/* const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const typesAddedToUnion = [];
|
||||||
|
Object.keys(newTypeMap).forEach(typeName => {
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (!(oldType instanceof GraphQLUnionType) ||
|
||||||
|
!(newType instanceof GraphQLUnionType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const typeNamesInOldUnion = Object.create(null);
|
||||||
|
oldType.getTypes().forEach(type => {
|
||||||
|
typeNamesInOldUnion[type.name] = true;
|
||||||
|
});
|
||||||
|
newType.getTypes().forEach(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.
|
||||||
|
*/
|
||||||
|
public static function findValuesRemovedFromEnums(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/* const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const valuesRemovedFromEnums = [];
|
||||||
|
Object.keys(oldTypeMap).forEach(typeName => {
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (!(oldType instanceof GraphQLEnumType) ||
|
||||||
|
!(newType instanceof GraphQLEnumType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const valuesInNewEnum = Object.create(null);
|
||||||
|
newType.getValues().forEach(value => {
|
||||||
|
valuesInNewEnum[value.name] = true;
|
||||||
|
});
|
||||||
|
oldType.getValues().forEach(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.
|
||||||
|
*/
|
||||||
|
public static function findValuesAddedToEnums(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/* const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
|
||||||
|
const valuesAddedToEnums = [];
|
||||||
|
Object.keys(oldTypeMap).forEach(typeName => {
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (!(oldType instanceof GraphQLEnumType) ||
|
||||||
|
!(newType instanceof GraphQLEnumType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const valuesInOldEnum = Object.create(null);
|
||||||
|
oldType.getValues().forEach(value => {
|
||||||
|
valuesInOldEnum[value.name] = true;
|
||||||
|
});
|
||||||
|
newType.getValues().forEach(value => {
|
||||||
|
if (!valuesInOldEnum[value.name]) {
|
||||||
|
valuesAddedToEnums.push({
|
||||||
|
type: DangerousChangeType.VALUE_ADDED_TO_ENUM,
|
||||||
|
description: `${value.name} was added to enum type ${typeName}.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return valuesAddedToEnums;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function findInterfacesRemovedFromObjectTypes(
|
||||||
|
$oldSchema, $newSchema
|
||||||
|
) {
|
||||||
|
/* const oldTypeMap = oldSchema.getTypeMap();
|
||||||
|
const newTypeMap = newSchema.getTypeMap();
|
||||||
|
const breakingChanges = [];
|
||||||
|
|
||||||
|
Object.keys(oldTypeMap).forEach(typeName => {
|
||||||
|
const oldType = oldTypeMap[typeName];
|
||||||
|
const newType = newTypeMap[typeName];
|
||||||
|
if (
|
||||||
|
!(oldType instanceof GraphQLObjectType) ||
|
||||||
|
!(newType instanceof GraphQLObjectType)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldInterfaces = oldType.getInterfaces();
|
||||||
|
const newInterfaces = newType.getInterfaces();
|
||||||
|
oldInterfaces.forEach(oldInterface => {
|
||||||
|
if (!newInterfaces.some(int => int.name === oldInterface.name)) {
|
||||||
|
breakingChanges.push({
|
||||||
|
type: BreakingChangeType.INTERFACE_REMOVED_FROM_OBJECT,
|
||||||
|
description: `${typeName} no longer implements interface ` +
|
||||||
|
`${oldInterface.name}.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return breakingChanges;*/
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user