@graphql-inspector/core 3.0.2 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/index.d.ts +1 -1
- package/index.js +28 -17
- package/index.mjs +28 -17
- package/package.json +2 -2
- package/utils/compare.d.ts +2 -2
- package/utils/isDeprecated.d.ts +2 -0
package/README.md
CHANGED
|
@@ -36,17 +36,17 @@ import {
|
|
|
36
36
|
Change,
|
|
37
37
|
InvalidDocument,
|
|
38
38
|
SimilarMap,
|
|
39
|
-
SchemaCoverage
|
|
40
|
-
} from '@graphql-inspector/core'
|
|
39
|
+
SchemaCoverage
|
|
40
|
+
} from '@graphql-inspector/core'
|
|
41
41
|
|
|
42
42
|
// diff
|
|
43
|
-
const changes: Change[] = diff(schemaA, schemaB)
|
|
43
|
+
const changes: Change[] = diff(schemaA, schemaB)
|
|
44
44
|
// validate
|
|
45
|
-
const invalid: InvalidDocument[] = validate(documentsGlob, schema)
|
|
45
|
+
const invalid: InvalidDocument[] = validate(documentsGlob, schema)
|
|
46
46
|
// similar
|
|
47
|
-
const similar: SimilarMap = similar(schema, typename, threshold)
|
|
47
|
+
const similar: SimilarMap = similar(schema, typename, threshold)
|
|
48
48
|
// coverage
|
|
49
|
-
const schemaCoverage: SchemaCoverage = coverage(schema, documents)
|
|
49
|
+
const schemaCoverage: SchemaCoverage = coverage(schema, documents)
|
|
50
50
|
// ...
|
|
51
51
|
```
|
|
52
52
|
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { diff, DiffRule, Rule, CompletionArgs, CompletionHandler, UsageHandler } from './diff';
|
|
1
|
+
export { diff, DiffRule, Rule, CompletionArgs, CompletionHandler, UsageHandler, } from './diff';
|
|
2
2
|
export { validate, InvalidDocument } from './validate';
|
|
3
3
|
export { similar, SimilarMap } from './similar';
|
|
4
4
|
export * from './coverage';
|
package/index.js
CHANGED
|
@@ -78,6 +78,20 @@ function compareLists(oldList, newList, callbacks) {
|
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
function isDeprecated(fieldOrEnumValue) {
|
|
82
|
+
var _a, _b;
|
|
83
|
+
if ('isDeprecated' in fieldOrEnumValue) {
|
|
84
|
+
return fieldOrEnumValue['isDeprecated'];
|
|
85
|
+
}
|
|
86
|
+
if (fieldOrEnumValue.deprecationReason != null) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
if ((_b = (_a = fieldOrEnumValue.astNode) === null || _a === void 0 ? void 0 : _a.directives) === null || _b === void 0 ? void 0 : _b.some((directive) => directive.name.value === 'deprecated')) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
81
95
|
function safeChangeForField(oldType, newType) {
|
|
82
96
|
if (!graphql.isWrappingType(oldType) && !graphql.isWrappingType(newType)) {
|
|
83
97
|
return oldType.toString() === newType.toString();
|
|
@@ -120,7 +134,7 @@ function getTypePrefix(type) {
|
|
|
120
134
|
[graphql.Kind.ENUM_TYPE_DEFINITION]: 'enum',
|
|
121
135
|
[graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION]: 'input',
|
|
122
136
|
};
|
|
123
|
-
return kindsMap[kind];
|
|
137
|
+
return kindsMap[kind.toString()];
|
|
124
138
|
}
|
|
125
139
|
function isPrimitive(type) {
|
|
126
140
|
return (['String', 'Int', 'Float', 'Boolean', 'ID'].indexOf(typeof type === 'string' ? type : type.name) !== -1);
|
|
@@ -155,7 +169,7 @@ function findDeprecatedUsages(schema, ast) {
|
|
|
155
169
|
},
|
|
156
170
|
Field(node) {
|
|
157
171
|
const fieldDef = typeInfo.getFieldDef();
|
|
158
|
-
if (fieldDef && fieldDef
|
|
172
|
+
if (fieldDef && isDeprecated(fieldDef)) {
|
|
159
173
|
const parentType = typeInfo.getParentType();
|
|
160
174
|
if (parentType) {
|
|
161
175
|
const reason = fieldDef.deprecationReason;
|
|
@@ -165,7 +179,7 @@ function findDeprecatedUsages(schema, ast) {
|
|
|
165
179
|
},
|
|
166
180
|
EnumValue(node) {
|
|
167
181
|
const enumVal = typeInfo.getEnumValue();
|
|
168
|
-
if (enumVal && enumVal
|
|
182
|
+
if (enumVal && isDeprecated(enumVal)) {
|
|
169
183
|
const type = graphql.getNamedType(typeInfo.getInputType());
|
|
170
184
|
if (type) {
|
|
171
185
|
const reason = enumVal.deprecationReason;
|
|
@@ -476,7 +490,7 @@ function enumValueRemoved(oldEnum, value) {
|
|
|
476
490
|
reason: `Removing an enum value will cause existing queries that use this enum value to error.`,
|
|
477
491
|
},
|
|
478
492
|
type: exports.ChangeType.EnumValueRemoved,
|
|
479
|
-
message: `Enum value '${value.name}' ${value
|
|
493
|
+
message: `Enum value '${value.name}' ${isDeprecated(value) ? '(deprecated) ' : ''}was removed from enum '${oldEnum.name}'`,
|
|
480
494
|
path: [oldEnum.name, value.name].join('.'),
|
|
481
495
|
};
|
|
482
496
|
}
|
|
@@ -559,7 +573,7 @@ function changesInEnum(oldEnum, newEnum, addChange) {
|
|
|
559
573
|
addChange(enumValueDeprecationReasonChanged(newEnum, oldValue, newValue));
|
|
560
574
|
}
|
|
561
575
|
}
|
|
562
|
-
}
|
|
576
|
+
},
|
|
563
577
|
});
|
|
564
578
|
}
|
|
565
579
|
|
|
@@ -760,7 +774,7 @@ function fieldRemoved(type, field) {
|
|
|
760
774
|
: `Removing a field is a breaking change. It is preferable to deprecate the field before removing it.`,
|
|
761
775
|
},
|
|
762
776
|
type: exports.ChangeType.FieldRemoved,
|
|
763
|
-
message: `Field '${field.name}' ${field
|
|
777
|
+
message: `Field '${field.name}' ${isDeprecated(field) ? '(deprecated) ' : ''}was removed from ${entity} '${type.name}'`,
|
|
764
778
|
path: [type.name, field.name].join('.'),
|
|
765
779
|
};
|
|
766
780
|
}
|
|
@@ -956,10 +970,7 @@ function wordLetterPairs(str) {
|
|
|
956
970
|
return flattenDeep(pairs);
|
|
957
971
|
}
|
|
958
972
|
function safeString(obj) {
|
|
959
|
-
|
|
960
|
-
return `${obj}`;
|
|
961
|
-
}
|
|
962
|
-
return inspect(obj);
|
|
973
|
+
return inspect(obj).replace(/\[Object\: null prototype\] /g, '');
|
|
963
974
|
}
|
|
964
975
|
|
|
965
976
|
function fieldArgumentDescriptionChanged(type, field, oldArg, newArg) {
|
|
@@ -1036,8 +1047,8 @@ function changesInField(type, oldField, newField, addChange) {
|
|
|
1036
1047
|
addChange(fieldDescriptionChanged(type, oldField, newField));
|
|
1037
1048
|
}
|
|
1038
1049
|
}
|
|
1039
|
-
if (isNotEqual(oldField
|
|
1040
|
-
if (newField
|
|
1050
|
+
if (isNotEqual(isDeprecated(oldField), isDeprecated(newField))) {
|
|
1051
|
+
if (isDeprecated(newField)) {
|
|
1041
1052
|
addChange(fieldDeprecationAdded(type, newField));
|
|
1042
1053
|
}
|
|
1043
1054
|
else {
|
|
@@ -1067,7 +1078,7 @@ function changesInField(type, oldField, newField, addChange) {
|
|
|
1067
1078
|
},
|
|
1068
1079
|
onMutual(arg) {
|
|
1069
1080
|
changesInArgument(type, oldField, arg.oldVersion, arg.newVersion, addChange);
|
|
1070
|
-
}
|
|
1081
|
+
},
|
|
1071
1082
|
});
|
|
1072
1083
|
}
|
|
1073
1084
|
|
|
@@ -1259,7 +1270,7 @@ const suppressRemovalOfDeprecatedField = ({ changes, oldSchema, }) => {
|
|
|
1259
1270
|
const type = oldSchema.getType(typeName);
|
|
1260
1271
|
if (graphql.isObjectType(type) || graphql.isInterfaceType(type)) {
|
|
1261
1272
|
const field = type.getFields()[fieldName];
|
|
1262
|
-
if (field
|
|
1273
|
+
if (isDeprecated(field)) {
|
|
1263
1274
|
return Object.assign(Object.assign({}, change), { criticality: Object.assign(Object.assign({}, change.criticality), { level: exports.CriticalityLevel.Dangerous }) });
|
|
1264
1275
|
}
|
|
1265
1276
|
}
|
|
@@ -1271,7 +1282,7 @@ const suppressRemovalOfDeprecatedField = ({ changes, oldSchema, }) => {
|
|
|
1271
1282
|
const type = oldSchema.getType(enumName);
|
|
1272
1283
|
if (graphql.isEnumType(type)) {
|
|
1273
1284
|
const item = type.getValue(enumItem);
|
|
1274
|
-
if (item && item
|
|
1285
|
+
if (item && isDeprecated(item)) {
|
|
1275
1286
|
return Object.assign(Object.assign({}, change), { criticality: Object.assign(Object.assign({}, change.criticality), { level: exports.CriticalityLevel.Dangerous }) });
|
|
1276
1287
|
}
|
|
1277
1288
|
}
|
|
@@ -1513,7 +1524,7 @@ function validate(schema, sources, options) {
|
|
|
1513
1524
|
.filter((doc) => doc.hasOperations)
|
|
1514
1525
|
.forEach((doc) => {
|
|
1515
1526
|
const docWithOperations = {
|
|
1516
|
-
kind:
|
|
1527
|
+
kind: graphql.Kind.DOCUMENT,
|
|
1517
1528
|
definitions: doc.operations.map((d) => d.node),
|
|
1518
1529
|
};
|
|
1519
1530
|
const extractedFragments = (extractFragments(graphql.print(docWithOperations)) || [])
|
|
@@ -1524,7 +1535,7 @@ function validate(schema, sources, options) {
|
|
|
1524
1535
|
// remove duplicates
|
|
1525
1536
|
.filter((def, i, all) => all.findIndex((item) => item.name.value === def.name.value) === i);
|
|
1526
1537
|
const merged = {
|
|
1527
|
-
kind:
|
|
1538
|
+
kind: graphql.Kind.DOCUMENT,
|
|
1528
1539
|
definitions: [...docWithOperations.definitions, ...extractedFragments],
|
|
1529
1540
|
};
|
|
1530
1541
|
let transformedSchema = config.apollo
|
package/index.mjs
CHANGED
|
@@ -72,6 +72,20 @@ function compareLists(oldList, newList, callbacks) {
|
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
function isDeprecated(fieldOrEnumValue) {
|
|
76
|
+
var _a, _b;
|
|
77
|
+
if ('isDeprecated' in fieldOrEnumValue) {
|
|
78
|
+
return fieldOrEnumValue['isDeprecated'];
|
|
79
|
+
}
|
|
80
|
+
if (fieldOrEnumValue.deprecationReason != null) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
if ((_b = (_a = fieldOrEnumValue.astNode) === null || _a === void 0 ? void 0 : _a.directives) === null || _b === void 0 ? void 0 : _b.some((directive) => directive.name.value === 'deprecated')) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
75
89
|
function safeChangeForField(oldType, newType) {
|
|
76
90
|
if (!isWrappingType(oldType) && !isWrappingType(newType)) {
|
|
77
91
|
return oldType.toString() === newType.toString();
|
|
@@ -114,7 +128,7 @@ function getTypePrefix(type) {
|
|
|
114
128
|
[Kind.ENUM_TYPE_DEFINITION]: 'enum',
|
|
115
129
|
[Kind.INPUT_OBJECT_TYPE_DEFINITION]: 'input',
|
|
116
130
|
};
|
|
117
|
-
return kindsMap[kind];
|
|
131
|
+
return kindsMap[kind.toString()];
|
|
118
132
|
}
|
|
119
133
|
function isPrimitive(type) {
|
|
120
134
|
return (['String', 'Int', 'Float', 'Boolean', 'ID'].indexOf(typeof type === 'string' ? type : type.name) !== -1);
|
|
@@ -149,7 +163,7 @@ function findDeprecatedUsages(schema, ast) {
|
|
|
149
163
|
},
|
|
150
164
|
Field(node) {
|
|
151
165
|
const fieldDef = typeInfo.getFieldDef();
|
|
152
|
-
if (fieldDef && fieldDef
|
|
166
|
+
if (fieldDef && isDeprecated(fieldDef)) {
|
|
153
167
|
const parentType = typeInfo.getParentType();
|
|
154
168
|
if (parentType) {
|
|
155
169
|
const reason = fieldDef.deprecationReason;
|
|
@@ -159,7 +173,7 @@ function findDeprecatedUsages(schema, ast) {
|
|
|
159
173
|
},
|
|
160
174
|
EnumValue(node) {
|
|
161
175
|
const enumVal = typeInfo.getEnumValue();
|
|
162
|
-
if (enumVal && enumVal
|
|
176
|
+
if (enumVal && isDeprecated(enumVal)) {
|
|
163
177
|
const type = getNamedType(typeInfo.getInputType());
|
|
164
178
|
if (type) {
|
|
165
179
|
const reason = enumVal.deprecationReason;
|
|
@@ -472,7 +486,7 @@ function enumValueRemoved(oldEnum, value) {
|
|
|
472
486
|
reason: `Removing an enum value will cause existing queries that use this enum value to error.`,
|
|
473
487
|
},
|
|
474
488
|
type: ChangeType.EnumValueRemoved,
|
|
475
|
-
message: `Enum value '${value.name}' ${value
|
|
489
|
+
message: `Enum value '${value.name}' ${isDeprecated(value) ? '(deprecated) ' : ''}was removed from enum '${oldEnum.name}'`,
|
|
476
490
|
path: [oldEnum.name, value.name].join('.'),
|
|
477
491
|
};
|
|
478
492
|
}
|
|
@@ -555,7 +569,7 @@ function changesInEnum(oldEnum, newEnum, addChange) {
|
|
|
555
569
|
addChange(enumValueDeprecationReasonChanged(newEnum, oldValue, newValue));
|
|
556
570
|
}
|
|
557
571
|
}
|
|
558
|
-
}
|
|
572
|
+
},
|
|
559
573
|
});
|
|
560
574
|
}
|
|
561
575
|
|
|
@@ -756,7 +770,7 @@ function fieldRemoved(type, field) {
|
|
|
756
770
|
: `Removing a field is a breaking change. It is preferable to deprecate the field before removing it.`,
|
|
757
771
|
},
|
|
758
772
|
type: ChangeType.FieldRemoved,
|
|
759
|
-
message: `Field '${field.name}' ${field
|
|
773
|
+
message: `Field '${field.name}' ${isDeprecated(field) ? '(deprecated) ' : ''}was removed from ${entity} '${type.name}'`,
|
|
760
774
|
path: [type.name, field.name].join('.'),
|
|
761
775
|
};
|
|
762
776
|
}
|
|
@@ -952,10 +966,7 @@ function wordLetterPairs(str) {
|
|
|
952
966
|
return flattenDeep(pairs);
|
|
953
967
|
}
|
|
954
968
|
function safeString(obj) {
|
|
955
|
-
|
|
956
|
-
return `${obj}`;
|
|
957
|
-
}
|
|
958
|
-
return inspect(obj);
|
|
969
|
+
return inspect(obj).replace(/\[Object\: null prototype\] /g, '');
|
|
959
970
|
}
|
|
960
971
|
|
|
961
972
|
function fieldArgumentDescriptionChanged(type, field, oldArg, newArg) {
|
|
@@ -1032,8 +1043,8 @@ function changesInField(type, oldField, newField, addChange) {
|
|
|
1032
1043
|
addChange(fieldDescriptionChanged(type, oldField, newField));
|
|
1033
1044
|
}
|
|
1034
1045
|
}
|
|
1035
|
-
if (isNotEqual(oldField
|
|
1036
|
-
if (newField
|
|
1046
|
+
if (isNotEqual(isDeprecated(oldField), isDeprecated(newField))) {
|
|
1047
|
+
if (isDeprecated(newField)) {
|
|
1037
1048
|
addChange(fieldDeprecationAdded(type, newField));
|
|
1038
1049
|
}
|
|
1039
1050
|
else {
|
|
@@ -1063,7 +1074,7 @@ function changesInField(type, oldField, newField, addChange) {
|
|
|
1063
1074
|
},
|
|
1064
1075
|
onMutual(arg) {
|
|
1065
1076
|
changesInArgument(type, oldField, arg.oldVersion, arg.newVersion, addChange);
|
|
1066
|
-
}
|
|
1077
|
+
},
|
|
1067
1078
|
});
|
|
1068
1079
|
}
|
|
1069
1080
|
|
|
@@ -1255,7 +1266,7 @@ const suppressRemovalOfDeprecatedField = ({ changes, oldSchema, }) => {
|
|
|
1255
1266
|
const type = oldSchema.getType(typeName);
|
|
1256
1267
|
if (isObjectType(type) || isInterfaceType(type)) {
|
|
1257
1268
|
const field = type.getFields()[fieldName];
|
|
1258
|
-
if (field
|
|
1269
|
+
if (isDeprecated(field)) {
|
|
1259
1270
|
return Object.assign(Object.assign({}, change), { criticality: Object.assign(Object.assign({}, change.criticality), { level: CriticalityLevel.Dangerous }) });
|
|
1260
1271
|
}
|
|
1261
1272
|
}
|
|
@@ -1267,7 +1278,7 @@ const suppressRemovalOfDeprecatedField = ({ changes, oldSchema, }) => {
|
|
|
1267
1278
|
const type = oldSchema.getType(enumName);
|
|
1268
1279
|
if (isEnumType(type)) {
|
|
1269
1280
|
const item = type.getValue(enumItem);
|
|
1270
|
-
if (item && item
|
|
1281
|
+
if (item && isDeprecated(item)) {
|
|
1271
1282
|
return Object.assign(Object.assign({}, change), { criticality: Object.assign(Object.assign({}, change.criticality), { level: CriticalityLevel.Dangerous }) });
|
|
1272
1283
|
}
|
|
1273
1284
|
}
|
|
@@ -1509,7 +1520,7 @@ function validate(schema, sources, options) {
|
|
|
1509
1520
|
.filter((doc) => doc.hasOperations)
|
|
1510
1521
|
.forEach((doc) => {
|
|
1511
1522
|
const docWithOperations = {
|
|
1512
|
-
kind:
|
|
1523
|
+
kind: Kind.DOCUMENT,
|
|
1513
1524
|
definitions: doc.operations.map((d) => d.node),
|
|
1514
1525
|
};
|
|
1515
1526
|
const extractedFragments = (extractFragments(print(docWithOperations)) || [])
|
|
@@ -1520,7 +1531,7 @@ function validate(schema, sources, options) {
|
|
|
1520
1531
|
// remove duplicates
|
|
1521
1532
|
.filter((def, i, all) => all.findIndex((item) => item.name.value === def.name.value) === i);
|
|
1522
1533
|
const merged = {
|
|
1523
|
-
kind:
|
|
1534
|
+
kind: Kind.DOCUMENT,
|
|
1524
1535
|
definitions: [...docWithOperations.definitions, ...extractedFragments],
|
|
1525
1536
|
};
|
|
1526
1537
|
let transformedSchema = config.apollo
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-inspector/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.2",
|
|
4
4
|
"description": "Tooling for GraphQL. Compare GraphQL Schemas, check documents, find breaking changes, find similar types.",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"graphql": "^0.13.0 || ^14.0.0 || ^15.0.0"
|
|
7
|
+
"graphql": "^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"dependency-graph": "0.11.0",
|
package/utils/compare.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export declare function keyMap<T>(list: readonly T[], keyFn: (item: T) => string
|
|
|
2
2
|
export declare function isEqual<T>(a: T, b: T): boolean;
|
|
3
3
|
export declare function isNotEqual<T>(a: T, b: T): boolean;
|
|
4
4
|
export declare function isVoid<T>(a: T): boolean;
|
|
5
|
-
export declare function diffArrays(a:
|
|
6
|
-
export declare function unionArrays(a:
|
|
5
|
+
export declare function diffArrays<T>(a: T[] | readonly T[], b: T[] | readonly T[]): T[];
|
|
6
|
+
export declare function unionArrays<T>(a: T[] | readonly T[], b: T[] | readonly T[]): T[];
|
|
7
7
|
export declare function compareLists<T extends {
|
|
8
8
|
name: string;
|
|
9
9
|
}>(oldList: readonly T[], newList: readonly T[], callbacks?: {
|