10
10
11
11
import {
12
12
getNamedType ,
13
+ GraphQLScalarType ,
13
14
GraphQLEnumType ,
14
15
GraphQLInputObjectType ,
15
16
GraphQLInterfaceType ,
16
17
GraphQLObjectType ,
17
18
GraphQLUnionType ,
18
19
} from '../type/definition' ;
19
- import {
20
- GraphQLSchema ,
21
- } from '../type/schema' ;
20
+
21
+ import type { GraphQLNamedType } from '../type/definition' ;
22
+
23
+ import { GraphQLSchema } from '../type/schema' ;
22
24
23
25
export const BreakingChangeType = {
24
26
FIELD_CHANGED_KIND : 'FIELD_CHANGED_KIND' ,
@@ -59,14 +61,19 @@ export function findRemovedTypes(
59
61
oldSchema : GraphQLSchema ,
60
62
newSchema : GraphQLSchema
61
63
) : Array < BreakingChange > {
62
- const oldTypeNames = Object . keys ( oldSchema . getTypeMap ( ) ) ;
63
- const newTypes = newSchema . getTypeMap ( ) ;
64
- return oldTypeNames . filter ( typeName => ! newTypes [ typeName ] ) . map (
65
- type => ( {
66
- type : BreakingChangeType . TYPE_REMOVED ,
67
- description : `${ type } was removed` ,
68
- } )
69
- ) ;
64
+ const oldTypeMap = oldSchema . getTypeMap ( ) ;
65
+ const newTypeMap = newSchema . getTypeMap ( ) ;
66
+
67
+ const breakingChanges = [ ] ;
68
+ Object . keys ( oldTypeMap ) . forEach ( typeName => {
69
+ if ( ! newTypeMap [ typeName ] ) {
70
+ breakingChanges . push ( {
71
+ type : BreakingChangeType . TYPE_REMOVED ,
72
+ description : `${ typeName } was removed.` ,
73
+ } ) ;
74
+ }
75
+ } ) ;
76
+ return breakingChanges ;
70
77
}
71
78
72
79
/**
@@ -88,22 +95,36 @@ export function findTypesThatChangedKind(
88
95
const oldType = oldTypeMap [ typeName ] ;
89
96
const newType = newTypeMap [ typeName ] ;
90
97
if ( ! ( oldType instanceof newType . constructor ) ) {
91
- breakingChanges . push (
92
- {
93
- type : BreakingChangeType . TYPE_CHANGED_KIND ,
94
- description : `${ typeName } changed from ` +
95
- `${ addArticle ( oldType . constructor . prettyName ) } type to ` +
96
- `${ addArticle ( newType . constructor . prettyName ) } type` ,
97
- }
98
- ) ;
98
+ breakingChanges . push ( {
99
+ type : BreakingChangeType . TYPE_CHANGED_KIND ,
100
+ description : `${ typeName } changed from ` +
101
+ `${ typeKindName ( oldType ) } to ${ typeKindName ( newType ) } .`
102
+ } ) ;
99
103
}
100
104
} ) ;
101
105
return breakingChanges ;
102
106
}
103
107
104
- function addArticle ( typeKind : string ) : string {
105
- const article = [ 'A' , 'E' , 'I' , 'O' ] . includes ( typeKind . charAt ( 0 ) ) ? 'an' : 'a' ;
106
- return article + ' ' + typeKind ;
108
+ function typeKindName ( type : GraphQLNamedType ) : string {
109
+ if ( type instanceof GraphQLScalarType ) {
110
+ return 'a Scalar type' ;
111
+ }
112
+ if ( type instanceof GraphQLObjectType ) {
113
+ return 'an Object type' ;
114
+ }
115
+ if ( type instanceof GraphQLInterfaceType ) {
116
+ return 'an Interface type' ;
117
+ }
118
+ if ( type instanceof GraphQLUnionType ) {
119
+ return 'a Union type' ;
120
+ }
121
+ if ( type instanceof GraphQLEnumType ) {
122
+ return 'an Enum type' ;
123
+ }
124
+ if ( type instanceof GraphQLInputObjectType ) {
125
+ return 'an Input type' ;
126
+ }
127
+ throw new TypeError ( 'Unknown type ' + type . constructor . name ) ;
107
128
}
108
129
109
130
/**
@@ -136,27 +157,22 @@ export function findFieldsThatChangedType(
136
157
Object . keys ( oldTypeFieldsDef ) . forEach ( fieldName => {
137
158
// Check if the field is missing on the type in the new schema.
138
159
if ( ! ( fieldName in newTypeFieldsDef ) ) {
139
- breakingFieldChanges . push (
140
- {
141
- type : BreakingChangeType . FIELD_REMOVED ,
142
- description : `${ typeName } .${ fieldName } was removed` ,
143
- }
144
- ) ;
160
+ breakingFieldChanges . push ( {
161
+ type : BreakingChangeType . FIELD_REMOVED ,
162
+ description : `${ typeName } .${ fieldName } was removed.` ,
163
+ } ) ;
145
164
} else {
146
165
// Check if the field's type has changed in the new schema.
147
166
const oldFieldType = getNamedType ( oldTypeFieldsDef [ fieldName ] . type ) ;
148
167
const newFieldType = getNamedType ( newTypeFieldsDef [ fieldName ] . type ) ;
149
- if (
150
- oldFieldType && newFieldType &&
151
- ( oldFieldType . name !== newFieldType . name )
152
- ) {
153
- breakingFieldChanges . push (
154
- {
155
- type : BreakingChangeType . FIELD_CHANGED_KIND ,
156
- description : `${ typeName } .${ fieldName } changed type from ` +
157
- `${ oldFieldType . name } to ${ newFieldType . name } ` ,
158
- }
159
- ) ;
168
+ if ( oldFieldType &&
169
+ newFieldType &&
170
+ oldFieldType . name !== newFieldType . name ) {
171
+ breakingFieldChanges . push ( {
172
+ type : BreakingChangeType . FIELD_CHANGED_KIND ,
173
+ description : `${ typeName } .${ fieldName } changed type from ` +
174
+ `${ oldFieldType . name } to ${ newFieldType . name } .` ,
175
+ } ) ;
160
176
}
161
177
}
162
178
} ) ;
@@ -179,24 +195,20 @@ export function findTypesRemovedFromUnions(
179
195
Object . keys ( oldTypeMap ) . forEach ( typeName => {
180
196
const oldType = oldTypeMap [ typeName ] ;
181
197
const newType = newTypeMap [ typeName ] ;
182
- if (
183
- ! ( oldType instanceof GraphQLUnionType ) ||
184
- ! ( newType instanceof GraphQLUnionType )
185
- ) {
198
+ if ( ! ( oldType instanceof GraphQLUnionType ) ||
199
+ ! ( newType instanceof GraphQLUnionType ) ) {
186
200
return ;
187
201
}
188
- const typeNamesInNewUnion = new Set (
189
- newType . getTypes ( ) . map ( type => type . name )
190
- ) ;
191
- oldType . getTypes ( ) . forEach ( typeInOldUnion => {
192
- if ( ! typeNamesInNewUnion . has ( typeInOldUnion . name ) ) {
193
- typesRemovedFromUnion . push (
194
- {
195
- type : BreakingChangeType . TYPE_REMOVED_FROM_UNION ,
196
- description : `${ typeInOldUnion . name } was removed from union ` +
197
- `type ${ typeName } ` ,
198
- }
199
- ) ;
202
+ const typeNamesInNewUnion = Object . create ( null ) ;
203
+ newType . getTypes ( ) . forEach ( type => {
204
+ typeNamesInNewUnion [ type . name ] = true ;
205
+ } ) ;
206
+ oldType . getTypes ( ) . forEach ( type => {
207
+ if ( ! typeNamesInNewUnion [ type . name ] ) {
208
+ typesRemovedFromUnion . push ( {
209
+ type : BreakingChangeType . TYPE_REMOVED_FROM_UNION ,
210
+ description : `${ type . name } was removed from union type ${ typeName } .`
211
+ } ) ;
200
212
}
201
213
} ) ;
202
214
} ) ;
@@ -218,24 +230,20 @@ export function findValuesRemovedFromEnums(
218
230
Object . keys ( oldTypeMap ) . forEach ( typeName => {
219
231
const oldType = oldTypeMap [ typeName ] ;
220
232
const newType = newTypeMap [ typeName ] ;
221
- if (
222
- ! ( oldType instanceof GraphQLEnumType ) ||
223
- ! ( newType instanceof GraphQLEnumType )
224
- ) {
233
+ if ( ! ( oldType instanceof GraphQLEnumType ) ||
234
+ ! ( newType instanceof GraphQLEnumType ) ) {
225
235
return ;
226
236
}
227
- const valuesInNewEnum = new Set (
228
- newType . getValues ( ) . map ( value => value . name )
229
- ) ;
230
- oldType . getValues ( ) . forEach ( valueInOldEnum => {
231
- if ( ! valuesInNewEnum . has ( valueInOldEnum . name ) ) {
232
- valuesRemovedFromEnums . push (
233
- {
234
- type : BreakingChangeType . VALUE_REMOVED_FROM_ENUM ,
235
- description : `${ valueInOldEnum . name } was removed from enum ` +
236
- `type ${ typeName } ` ,
237
- }
238
- ) ;
237
+ const valuesInNewEnum = Object . create ( null ) ;
238
+ newType . getValues ( ) . forEach ( value => {
239
+ valuesInNewEnum [ value . name ] = true ;
240
+ } ) ;
241
+ oldType . getValues ( ) . forEach ( value => {
242
+ if ( ! valuesInNewEnum [ value . name ] ) {
243
+ valuesRemovedFromEnums . push ( {
244
+ type : BreakingChangeType . VALUE_REMOVED_FROM_ENUM ,
245
+ description : `${ value . name } was removed from enum type ${ typeName } .`
246
+ } ) ;
239
247
}
240
248
} ) ;
241
249
} ) ;
0 commit comments