@graphql-inspector/action 5.0.21 → 6.1.0
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/cjs/action/helpers/types.js +7 -1
- package/cjs/action/src/run.js +14 -1
- package/cjs/action/src/utils.js +12 -1
- package/cjs/core/src/diff/argument.js +5 -12
- package/cjs/core/src/diff/changes/argument.js +6 -4
- package/cjs/core/src/diff/changes/directive.js +9 -5
- package/cjs/core/src/diff/changes/field.js +3 -2
- package/cjs/core/src/diff/changes/input.js +8 -7
- package/cjs/core/src/diff/directive.js +2 -1
- package/cjs/core/src/diff/input.js +5 -11
- package/cjs/core/src/utils/graphql.js +43 -3
- package/cjs/core/src/validate/alias-count.js +5 -1
- package/cjs/core/src/validate/complexity.js +5 -1
- package/cjs/core/src/validate/directive-count.js +5 -1
- package/cjs/core/src/validate/query-depth.js +5 -1
- package/cjs/core/src/validate/token-count.js +5 -1
- package/cjs/run.js +14 -1
- package/cjs/utils.js +12 -1
- package/esm/action/helpers/types.js +6 -0
- package/esm/action/src/run.js +16 -3
- package/esm/action/src/utils.js +11 -1
- package/esm/core/src/diff/argument.js +6 -13
- package/esm/core/src/diff/changes/argument.js +7 -5
- package/esm/core/src/diff/changes/directive.js +10 -6
- package/esm/core/src/diff/changes/field.js +4 -3
- package/esm/core/src/diff/changes/input.js +9 -8
- package/esm/core/src/diff/directive.js +2 -1
- package/esm/core/src/diff/input.js +6 -12
- package/esm/core/src/utils/graphql.js +41 -4
- package/esm/core/src/validate/alias-count.js +5 -1
- package/esm/core/src/validate/complexity.js +5 -1
- package/esm/core/src/validate/directive-count.js +5 -1
- package/esm/core/src/validate/query-depth.js +5 -1
- package/esm/core/src/validate/token-count.js +5 -1
- package/esm/run.js +16 -3
- package/esm/utils.js +11 -1
- package/package.json +10 -10
- package/typings/action/helpers/types.d.cts +5 -0
- package/typings/action/helpers/types.d.ts +5 -0
- package/typings/action/src/utils.d.cts +2 -0
- package/typings/action/src/utils.d.ts +2 -0
- package/typings/core/src/diff/changes/change.d.cts +1 -1
- package/typings/core/src/diff/changes/change.d.ts +1 -1
- package/typings/core/src/diff/changes/directive.d.cts +3 -3
- package/typings/core/src/diff/changes/directive.d.ts +3 -3
- package/typings/core/src/diff/changes/type.d.cts +3 -3
- package/typings/core/src/diff/changes/type.d.ts +3 -3
- package/typings/core/src/utils/graphql.d.cts +15 -2
- package/typings/core/src/utils/graphql.d.ts +15 -2
- package/typings/utils.d.cts +2 -0
- package/typings/utils.d.ts +2 -0
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CheckConclusion = exports.CheckStatus = exports.AnnotationLevel = void 0;
|
|
3
|
+
exports.CheckConclusion = exports.CheckStatus = exports.AnnotationLevel = exports.AnnotationFilterLevel = void 0;
|
|
4
|
+
var AnnotationFilterLevel;
|
|
5
|
+
(function (AnnotationFilterLevel) {
|
|
6
|
+
AnnotationFilterLevel["All"] = "all";
|
|
7
|
+
AnnotationFilterLevel["Dangerous"] = "dangerous";
|
|
8
|
+
AnnotationFilterLevel["Breaking"] = "breaking";
|
|
9
|
+
})(AnnotationFilterLevel || (exports.AnnotationFilterLevel = AnnotationFilterLevel = {}));
|
|
4
10
|
var AnnotationLevel;
|
|
5
11
|
(function (AnnotationLevel) {
|
|
6
12
|
AnnotationLevel["Failure"] = "failure";
|
package/cjs/action/src/run.js
CHANGED
|
@@ -31,6 +31,10 @@ async function run() {
|
|
|
31
31
|
}
|
|
32
32
|
const useMerge = (0, utils_js_2.castToBoolean)(core.getInput('experimental_merge'), true);
|
|
33
33
|
const useAnnotations = (0, utils_js_2.castToBoolean)(core.getInput('annotations'));
|
|
34
|
+
const annotationLevel = core.getInput('annotation-level') || types_js_1.AnnotationFilterLevel.All;
|
|
35
|
+
if (!(0, utils_js_2.isAnnotationFilterLevel)(annotationLevel)) {
|
|
36
|
+
return core.setFailed(`Invalid annotation-level. Expected one of: ${Object.values(types_js_1.AnnotationFilterLevel).join(', ')}.`);
|
|
37
|
+
}
|
|
34
38
|
const failOnBreaking = (0, utils_js_2.castToBoolean)(core.getInput('fail-on-breaking'));
|
|
35
39
|
const endpoint = core.getInput('endpoint');
|
|
36
40
|
const approveLabel = core.getInput('approve-label') || 'approved-breaking-change';
|
|
@@ -76,7 +80,11 @@ async function run() {
|
|
|
76
80
|
}
|
|
77
81
|
let config;
|
|
78
82
|
if (onUsage) {
|
|
79
|
-
|
|
83
|
+
// real runtime require so ncc doesn't try to resolve it from the bundle
|
|
84
|
+
const checkUsage = process
|
|
85
|
+
// @ts-expect-error getBuiltinModule exists starting node v20.16.0
|
|
86
|
+
.getBuiltinModule('module')
|
|
87
|
+
.createRequire(import.meta.url)(onUsage);
|
|
80
88
|
if (checkUsage) {
|
|
81
89
|
config = {
|
|
82
90
|
checkUsage,
|
|
@@ -162,6 +170,11 @@ async function run() {
|
|
|
162
170
|
core.info(`Anotations are disabled. Skipping annotations...`);
|
|
163
171
|
annotations = [];
|
|
164
172
|
}
|
|
173
|
+
else if (annotationLevel !== types_js_1.AnnotationFilterLevel.All) {
|
|
174
|
+
annotations = annotations.filter(annotation => annotationLevel === types_js_1.AnnotationFilterLevel.Breaking
|
|
175
|
+
? annotation.annotation_level === types_js_1.AnnotationLevel.Failure
|
|
176
|
+
: annotation.annotation_level !== types_js_1.AnnotationLevel.Notice);
|
|
177
|
+
}
|
|
165
178
|
const summary = (0, utils_js_1.createSummary)(changes, 100, false);
|
|
166
179
|
const title = conclusion === types_js_1.CheckConclusion.Failure
|
|
167
180
|
? 'Something is wrong with your schema'
|
package/cjs/action/src/utils.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.batch = batch;
|
|
4
4
|
exports.castToBoolean = castToBoolean;
|
|
5
|
+
exports.isAnnotationFilterLevel = isAnnotationFilterLevel;
|
|
5
6
|
exports.getInputAsArray = getInputAsArray;
|
|
6
7
|
exports.resolveRule = resolveRule;
|
|
7
8
|
const tslib_1 = require("tslib");
|
|
@@ -9,6 +10,8 @@ const fs_1 = require("fs");
|
|
|
9
10
|
const core = tslib_1.__importStar(require("@actions/core"));
|
|
10
11
|
const commands_1 = require("@graphql-inspector/commands");
|
|
11
12
|
const core_1 = require("@graphql-inspector/core");
|
|
13
|
+
const types_js_1 = require("../helpers/types.js");
|
|
14
|
+
const annotationFilterLevels = Object.values(types_js_1.AnnotationFilterLevel);
|
|
12
15
|
function batch(items, limit) {
|
|
13
16
|
const batches = [];
|
|
14
17
|
const batchesNum = Math.ceil(items.length / limit);
|
|
@@ -38,6 +41,9 @@ function castToBoolean(value, defaultValue) {
|
|
|
38
41
|
}
|
|
39
42
|
return true;
|
|
40
43
|
}
|
|
44
|
+
function isAnnotationFilterLevel(value) {
|
|
45
|
+
return annotationFilterLevels.includes(value);
|
|
46
|
+
}
|
|
41
47
|
function getInputAsArray(name, options) {
|
|
42
48
|
return core
|
|
43
49
|
.getInput(name, options)
|
|
@@ -48,7 +54,12 @@ function getInputAsArray(name, options) {
|
|
|
48
54
|
function resolveRule(name) {
|
|
49
55
|
const filepath = (0, commands_1.ensureAbsolute)(name);
|
|
50
56
|
if ((0, fs_1.existsSync)(filepath)) {
|
|
51
|
-
|
|
57
|
+
// ncc rewrites bare require to its bundler require, which can't load files
|
|
58
|
+
// outside the bundle. createRequire gives us a real runtime require.
|
|
59
|
+
return (process
|
|
60
|
+
// @ts-expect-error getBuiltinModule exists starting node v20.16.0
|
|
61
|
+
.getBuiltinModule('module')
|
|
62
|
+
.createRequire(import.meta.url)(filepath));
|
|
52
63
|
}
|
|
53
64
|
return core_1.DiffRule[name];
|
|
54
65
|
}
|
|
@@ -3,28 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.changesInArgument = changesInArgument;
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
5
|
const compare_js_1 = require("../utils/compare.js");
|
|
6
|
+
const graphql_js_1 = require("../utils/graphql.js");
|
|
6
7
|
const argument_js_1 = require("./changes/argument.js");
|
|
7
8
|
const directive_usage_js_1 = require("./changes/directive-usage.js");
|
|
8
9
|
function changesInArgument(type, field, oldArg, newArg, addChange) {
|
|
9
10
|
if ((0, compare_js_1.isNotEqual)(oldArg?.description, newArg.description)) {
|
|
10
11
|
addChange((0, argument_js_1.fieldArgumentDescriptionChanged)(type, field, oldArg, newArg));
|
|
11
12
|
}
|
|
12
|
-
if ((0,
|
|
13
|
-
|
|
14
|
-
const diff = (0, compare_js_1.diffArrays)(oldArg.defaultValue, newArg.defaultValue);
|
|
15
|
-
if (diff.length > 0) {
|
|
16
|
-
addChange((0, argument_js_1.fieldArgumentDefaultChanged)(type, field, oldArg, newArg));
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
else if (JSON.stringify(oldArg?.defaultValue) !== JSON.stringify(newArg.defaultValue)) {
|
|
20
|
-
addChange((0, argument_js_1.fieldArgumentDefaultChanged)(type, field, oldArg, newArg));
|
|
21
|
-
}
|
|
13
|
+
if (!(0, graphql_js_1.defaultValuesAreEqual)(oldArg, newArg)) {
|
|
14
|
+
addChange((0, argument_js_1.fieldArgumentDefaultChanged)(type, field, oldArg, newArg));
|
|
22
15
|
}
|
|
23
16
|
if ((0, compare_js_1.isNotEqual)(oldArg?.type.toString(), newArg.type.toString())) {
|
|
24
17
|
addChange((0, argument_js_1.fieldArgumentTypeChanged)(type, field, oldArg, newArg));
|
|
25
18
|
}
|
|
26
|
-
if (newArg.astNode?.directives) {
|
|
27
|
-
(0, compare_js_1.compareDirectiveLists)(oldArg?.astNode?.directives || [], newArg.astNode
|
|
19
|
+
if (oldArg?.astNode?.directives || newArg.astNode?.directives) {
|
|
20
|
+
(0, compare_js_1.compareDirectiveLists)(oldArg?.astNode?.directives || [], newArg.astNode?.directives || [], {
|
|
28
21
|
onAdded(directive) {
|
|
29
22
|
addChange((0, directive_usage_js_1.directiveUsageAdded)(graphql_1.Kind.ARGUMENT, directive, {
|
|
30
23
|
argument: newArg,
|
|
@@ -65,11 +65,13 @@ function fieldArgumentDefaultChanged(type, field, oldArg, newArg) {
|
|
|
65
65
|
fieldName: field.name,
|
|
66
66
|
argumentName: newArg.name,
|
|
67
67
|
};
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
const oldDefaultValue = oldArg === null ? undefined : (0, graphql_js_1.getDefaultValue)(oldArg);
|
|
69
|
+
const newDefaultValue = (0, graphql_js_1.getDefaultValue)(newArg);
|
|
70
|
+
if (oldDefaultValue !== undefined) {
|
|
71
|
+
meta.oldDefaultValue = (0, string_js_1.safeString)(oldDefaultValue);
|
|
70
72
|
}
|
|
71
|
-
if (
|
|
72
|
-
meta.newDefaultValue = (0, string_js_1.safeString)(
|
|
73
|
+
if (newDefaultValue !== undefined) {
|
|
74
|
+
meta.newDefaultValue = (0, string_js_1.safeString)(newDefaultValue);
|
|
73
75
|
}
|
|
74
76
|
return fieldArgumentDefaultChangedFromMeta({
|
|
75
77
|
type: change_js_1.ChangeType.FieldArgumentDefaultChanged,
|
|
@@ -231,7 +231,9 @@ function directiveArgumentAdded(directive, arg, addedToNewDirective) {
|
|
|
231
231
|
directiveName: directive.name,
|
|
232
232
|
addedDirectiveArgumentName: arg.name,
|
|
233
233
|
addedDirectiveArgumentType: arg.type.toString(),
|
|
234
|
-
addedDirectiveDefaultValue:
|
|
234
|
+
addedDirectiveDefaultValue: (0, graphql_js_1.hasDefaultValue)(arg)
|
|
235
|
+
? (0, string_js_1.safeString)((0, graphql_js_1.getDefaultValue)(arg))
|
|
236
|
+
: undefined,
|
|
235
237
|
addedDirectiveArgumentTypeIsNonNull: (0, graphql_1.isNonNullType)(arg.type),
|
|
236
238
|
addedDirectiveArgumentDescription: arg.description ?? undefined,
|
|
237
239
|
addedToNewDirective,
|
|
@@ -319,11 +321,13 @@ function directiveArgumentDefaultValueChanged(directive, oldArg, newArg) {
|
|
|
319
321
|
directiveName: directive.name,
|
|
320
322
|
directiveArgumentName: newArg.name,
|
|
321
323
|
};
|
|
322
|
-
|
|
323
|
-
|
|
324
|
+
const oldDefaultValue = oldArg === null ? undefined : (0, graphql_js_1.getDefaultValue)(oldArg);
|
|
325
|
+
const newDefaultValue = (0, graphql_js_1.getDefaultValue)(newArg);
|
|
326
|
+
if (oldDefaultValue !== undefined) {
|
|
327
|
+
meta.oldDirectiveArgumentDefaultValue = (0, string_js_1.safeString)(oldDefaultValue);
|
|
324
328
|
}
|
|
325
|
-
if (
|
|
326
|
-
meta.newDirectiveArgumentDefaultValue = (0, string_js_1.safeString)(
|
|
329
|
+
if (newDefaultValue !== undefined) {
|
|
330
|
+
meta.newDirectiveArgumentDefaultValue = (0, string_js_1.safeString)(newDefaultValue);
|
|
327
331
|
}
|
|
328
332
|
return directiveArgumentDefaultValueChangedFromMeta({
|
|
329
333
|
type: change_js_1.ChangeType.DirectiveArgumentDefaultValueChanged,
|
|
@@ -327,7 +327,8 @@ function fieldArgumentAddedFromMeta(args) {
|
|
|
327
327
|
};
|
|
328
328
|
}
|
|
329
329
|
function fieldArgumentAdded(type, field, arg, addedToNewField) {
|
|
330
|
-
const
|
|
330
|
+
const hasDefault = (0, graphql_js_1.hasDefaultValue)(arg);
|
|
331
|
+
const isBreaking = (0, graphql_1.isNonNullType)(arg.type) && !hasDefault;
|
|
331
332
|
return fieldArgumentAddedFromMeta({
|
|
332
333
|
type: change_js_1.ChangeType.FieldArgumentAdded,
|
|
333
334
|
meta: {
|
|
@@ -335,7 +336,7 @@ function fieldArgumentAdded(type, field, arg, addedToNewField) {
|
|
|
335
336
|
fieldName: field.name,
|
|
336
337
|
addedArgumentName: arg.name,
|
|
337
338
|
addedArgumentType: arg.type.toString(),
|
|
338
|
-
hasDefaultValue:
|
|
339
|
+
hasDefaultValue: hasDefault,
|
|
339
340
|
addedToNewField,
|
|
340
341
|
isAddedFieldArgumentBreaking: isBreaking,
|
|
341
342
|
},
|
|
@@ -84,6 +84,7 @@ function inputFieldAddedFromMeta(args) {
|
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
function inputFieldAdded(input, field, addedToNewType) {
|
|
87
|
+
const defaultValue = (0, graphql_js_1.getDefaultValue)(field);
|
|
87
88
|
return inputFieldAddedFromMeta({
|
|
88
89
|
type: change_js_1.ChangeType.InputFieldAdded,
|
|
89
90
|
meta: {
|
|
@@ -91,9 +92,7 @@ function inputFieldAdded(input, field, addedToNewType) {
|
|
|
91
92
|
addedInputFieldName: field.name,
|
|
92
93
|
isAddedInputFieldTypeNullable: !(0, graphql_1.isNonNullType)(field.type),
|
|
93
94
|
addedInputFieldType: field.type.toString(),
|
|
94
|
-
...(field.defaultValue
|
|
95
|
-
? {}
|
|
96
|
-
: { addedFieldDefault: (0, string_js_1.safeString)(field.defaultValue) }),
|
|
95
|
+
...((0, graphql_js_1.hasDefaultValue)(field) ? { addedFieldDefault: (0, string_js_1.safeString)(defaultValue) } : {}),
|
|
97
96
|
addedToNewType,
|
|
98
97
|
},
|
|
99
98
|
});
|
|
@@ -196,11 +195,13 @@ function inputFieldDefaultValueChanged(input, oldField, newField) {
|
|
|
196
195
|
inputName: input.name,
|
|
197
196
|
inputFieldName: newField.name,
|
|
198
197
|
};
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
const oldDefaultValue = (0, graphql_js_1.getDefaultValue)(oldField);
|
|
199
|
+
const newDefaultValue = (0, graphql_js_1.getDefaultValue)(newField);
|
|
200
|
+
if (oldDefaultValue !== undefined) {
|
|
201
|
+
meta.oldDefaultValue = (0, string_js_1.safeString)(oldDefaultValue);
|
|
201
202
|
}
|
|
202
|
-
if (
|
|
203
|
-
meta.newDefaultValue = (0, string_js_1.safeString)(
|
|
203
|
+
if (newDefaultValue !== undefined) {
|
|
204
|
+
meta.newDefaultValue = (0, string_js_1.safeString)(newDefaultValue);
|
|
204
205
|
}
|
|
205
206
|
return inputFieldDefaultValueChangedFromMeta({
|
|
206
207
|
type: change_js_1.ChangeType.InputFieldDefaultValueChanged,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.changesInDirective = changesInDirective;
|
|
4
4
|
const compare_js_1 = require("../utils/compare.js");
|
|
5
|
+
const graphql_js_1 = require("../utils/graphql.js");
|
|
5
6
|
const directive_js_1 = require("./changes/directive.js");
|
|
6
7
|
function changesInDirective(oldDirective, newDirective, addChange) {
|
|
7
8
|
if ((0, compare_js_1.isNotEqual)(oldDirective?.description, newDirective.description)) {
|
|
@@ -41,7 +42,7 @@ function changesInDirectiveArgument(directive, oldArg, newArg, addChange) {
|
|
|
41
42
|
if ((0, compare_js_1.isNotEqual)(oldArg?.description, newArg.description)) {
|
|
42
43
|
addChange((0, directive_js_1.directiveArgumentDescriptionChanged)(directive, oldArg, newArg));
|
|
43
44
|
}
|
|
44
|
-
if ((0,
|
|
45
|
+
if (!(0, graphql_js_1.defaultValuesAreEqual)(oldArg, newArg)) {
|
|
45
46
|
addChange((0, directive_js_1.directiveArgumentDefaultValueChanged)(directive, oldArg, newArg));
|
|
46
47
|
}
|
|
47
48
|
if ((0, compare_js_1.isNotEqual)(oldArg.type.toString(), newArg.type.toString())) {
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.changesInInputObject = changesInInputObject;
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
5
|
const compare_js_1 = require("../utils/compare.js");
|
|
6
|
+
const graphql_js_1 = require("../utils/graphql.js");
|
|
6
7
|
const directive_usage_js_1 = require("./changes/directive-usage.js");
|
|
7
8
|
const input_js_1 = require("./changes/input.js");
|
|
8
9
|
function changesInInputObject(oldInput, newInput, addChange) {
|
|
@@ -46,22 +47,15 @@ function changesInInputField(input, oldField, newField, addChange) {
|
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
if (!(0, compare_js_1.isVoid)(oldField)) {
|
|
49
|
-
if ((0,
|
|
50
|
-
|
|
51
|
-
if ((0, compare_js_1.diffArrays)(oldField.defaultValue, newField.defaultValue).length > 0) {
|
|
52
|
-
addChange((0, input_js_1.inputFieldDefaultValueChanged)(input, oldField, newField));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
else if (JSON.stringify(oldField?.defaultValue) !== JSON.stringify(newField.defaultValue)) {
|
|
56
|
-
addChange((0, input_js_1.inputFieldDefaultValueChanged)(input, oldField, newField));
|
|
57
|
-
}
|
|
50
|
+
if (!(0, graphql_js_1.defaultValuesAreEqual)(oldField, newField)) {
|
|
51
|
+
addChange((0, input_js_1.inputFieldDefaultValueChanged)(input, oldField, newField));
|
|
58
52
|
}
|
|
59
53
|
if (!(0, compare_js_1.isVoid)(oldField) && (0, compare_js_1.isNotEqual)(oldField.type.toString(), newField.type.toString())) {
|
|
60
54
|
addChange((0, input_js_1.inputFieldTypeChanged)(input, oldField, newField));
|
|
61
55
|
}
|
|
62
56
|
}
|
|
63
|
-
if (newField.astNode?.directives) {
|
|
64
|
-
(0, compare_js_1.compareDirectiveLists)(oldField?.astNode?.directives || [], newField.astNode
|
|
57
|
+
if (oldField?.astNode?.directives || newField.astNode?.directives) {
|
|
58
|
+
(0, compare_js_1.compareDirectiveLists)(oldField?.astNode?.directives || [], newField.astNode?.directives || [], {
|
|
65
59
|
onAdded(directive) {
|
|
66
60
|
addChange((0, directive_usage_js_1.directiveUsageAdded)(graphql_1.Kind.INPUT_VALUE_DEFINITION, directive, {
|
|
67
61
|
type: input,
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefaultValue = getDefaultValue;
|
|
4
|
+
exports.hasDefaultValue = hasDefaultValue;
|
|
5
|
+
exports.defaultValuesAreEqual = defaultValuesAreEqual;
|
|
3
6
|
exports.safeChangeForField = safeChangeForField;
|
|
4
7
|
exports.safeChangeForInputValue = safeChangeForInputValue;
|
|
5
8
|
exports.getKind = getKind;
|
|
@@ -12,6 +15,43 @@ exports.removeDirectives = removeDirectives;
|
|
|
12
15
|
exports.getReachableTypes = getReachableTypes;
|
|
13
16
|
const graphql_1 = require("graphql");
|
|
14
17
|
const is_deprecated_js_1 = require("./is-deprecated.js");
|
|
18
|
+
function getDefaultValue(inputValue) {
|
|
19
|
+
if (inputValue.default !== undefined) {
|
|
20
|
+
if (inputValue.default.literal !== undefined) {
|
|
21
|
+
return (0, graphql_1.valueFromAST)(inputValue.default.literal, inputValue.type);
|
|
22
|
+
}
|
|
23
|
+
return (0, graphql_1.coerceInputValue)(inputValue.default.value, inputValue.type);
|
|
24
|
+
}
|
|
25
|
+
return inputValue.defaultValue;
|
|
26
|
+
}
|
|
27
|
+
function hasDefaultValue(inputValue) {
|
|
28
|
+
return inputValue.default !== undefined || inputValue.defaultValue !== undefined;
|
|
29
|
+
}
|
|
30
|
+
function defaultValuesAreEqual(oldInputValue, newInputValue) {
|
|
31
|
+
return defaultValueEquals(oldInputValue == null ? undefined : getDefaultValue(oldInputValue), getDefaultValue(newInputValue));
|
|
32
|
+
}
|
|
33
|
+
function defaultValueEquals(oldValue, newValue) {
|
|
34
|
+
if (Object.is(oldValue, newValue)) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (Array.isArray(oldValue) && Array.isArray(newValue)) {
|
|
38
|
+
return (oldValue.length === newValue.length &&
|
|
39
|
+
oldValue.every((value, index) => defaultValueEquals(value, newValue[index])));
|
|
40
|
+
}
|
|
41
|
+
if (oldValue !== null &&
|
|
42
|
+
newValue !== null &&
|
|
43
|
+
typeof oldValue === 'object' &&
|
|
44
|
+
typeof newValue === 'object') {
|
|
45
|
+
const oldRecord = oldValue;
|
|
46
|
+
const newRecord = newValue;
|
|
47
|
+
const oldKeys = Object.keys(oldRecord);
|
|
48
|
+
const newKeys = Object.keys(newRecord);
|
|
49
|
+
return (oldKeys.length === newKeys.length &&
|
|
50
|
+
oldKeys.every(key => Object.prototype.hasOwnProperty.call(newRecord, key) &&
|
|
51
|
+
defaultValueEquals(oldRecord[key], newRecord[key])));
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
15
55
|
function safeChangeForField(oldType, newType) {
|
|
16
56
|
if (!(0, graphql_1.isWrappingType)(oldType) && !(0, graphql_1.isWrappingType)(newType)) {
|
|
17
57
|
return oldType.toString() === newType.toString();
|
|
@@ -81,7 +121,7 @@ function findDeprecatedUsages(schema, ast) {
|
|
|
81
121
|
if (reason) {
|
|
82
122
|
const fieldDef = typeInfo.getFieldDef();
|
|
83
123
|
if (fieldDef) {
|
|
84
|
-
errors.push(new graphql_1.GraphQLError(`The argument '${argument?.name}' of '${fieldDef.name}' is deprecated. ${reason}`, [node]));
|
|
124
|
+
errors.push(new graphql_1.GraphQLError(`The argument '${argument?.name}' of '${fieldDef.name}' is deprecated. ${reason}`, { nodes: [node] }));
|
|
85
125
|
}
|
|
86
126
|
}
|
|
87
127
|
}
|
|
@@ -92,7 +132,7 @@ function findDeprecatedUsages(schema, ast) {
|
|
|
92
132
|
const parentType = typeInfo.getParentType();
|
|
93
133
|
if (parentType) {
|
|
94
134
|
const reason = fieldDef.deprecationReason;
|
|
95
|
-
errors.push(new graphql_1.GraphQLError(`The field '${parentType.name}.${fieldDef.name}' is deprecated.${reason ? ' ' + reason : ''}`, [node]));
|
|
135
|
+
errors.push(new graphql_1.GraphQLError(`The field '${parentType.name}.${fieldDef.name}' is deprecated.${reason ? ' ' + reason : ''}`, { nodes: [node] }));
|
|
96
136
|
}
|
|
97
137
|
}
|
|
98
138
|
},
|
|
@@ -102,7 +142,7 @@ function findDeprecatedUsages(schema, ast) {
|
|
|
102
142
|
const type = (0, graphql_1.getNamedType)(typeInfo.getInputType());
|
|
103
143
|
if (type) {
|
|
104
144
|
const reason = enumVal.deprecationReason;
|
|
105
|
-
errors.push(new graphql_1.GraphQLError(`The enum value '${type.name}.${enumVal.name}' is deprecated.${reason ? ' ' + reason : ''}`, [node]));
|
|
145
|
+
errors.push(new graphql_1.GraphQLError(`The enum value '${type.name}.${enumVal.name}' is deprecated.${reason ? ' ' + reason : ''}`, { nodes: [node] }));
|
|
106
146
|
}
|
|
107
147
|
}
|
|
108
148
|
},
|
|
@@ -11,7 +11,11 @@ function validateAliasCount({ source, doc, maxAliasCount, fragmentGraph, }) {
|
|
|
11
11
|
}
|
|
12
12
|
const aliasCount = countAliases(definition, getFragmentByFragmentName);
|
|
13
13
|
if (aliasCount > maxAliasCount) {
|
|
14
|
-
return new graphql_1.GraphQLError(`Too many aliases (${aliasCount}). Maximum allowed is ${maxAliasCount}`,
|
|
14
|
+
return new graphql_1.GraphQLError(`Too many aliases (${aliasCount}). Maximum allowed is ${maxAliasCount}`, {
|
|
15
|
+
source,
|
|
16
|
+
nodes: [definition],
|
|
17
|
+
positions: definition.loc?.start ? [definition.loc.start] : undefined,
|
|
18
|
+
});
|
|
15
19
|
}
|
|
16
20
|
}
|
|
17
21
|
}
|
|
@@ -11,7 +11,11 @@ function validateComplexity({ source, doc, maxComplexityScore, config, fragmentG
|
|
|
11
11
|
}
|
|
12
12
|
const complexityScore = calculateOperationComplexity(definition, config, getFragmentByFragmentName);
|
|
13
13
|
if (complexityScore > maxComplexityScore) {
|
|
14
|
-
return new graphql_1.GraphQLError(`Too high complexity score (${complexityScore}). Maximum allowed is ${maxComplexityScore}`,
|
|
14
|
+
return new graphql_1.GraphQLError(`Too high complexity score (${complexityScore}). Maximum allowed is ${maxComplexityScore}`, {
|
|
15
|
+
nodes: [definition],
|
|
16
|
+
positions: definition.loc?.start ? [definition.loc.start] : undefined,
|
|
17
|
+
source,
|
|
18
|
+
});
|
|
15
19
|
}
|
|
16
20
|
}
|
|
17
21
|
}
|
|
@@ -11,7 +11,11 @@ function validateDirectiveCount({ source, doc, maxDirectiveCount, fragmentGraph,
|
|
|
11
11
|
}
|
|
12
12
|
const directiveCount = countDirectives(definition, getFragmentByFragmentName);
|
|
13
13
|
if (directiveCount > maxDirectiveCount) {
|
|
14
|
-
return new graphql_1.GraphQLError(`Too many directives (${directiveCount}). Maximum allowed is ${maxDirectiveCount}`,
|
|
14
|
+
return new graphql_1.GraphQLError(`Too many directives (${directiveCount}). Maximum allowed is ${maxDirectiveCount}`, {
|
|
15
|
+
nodes: [definition],
|
|
16
|
+
source,
|
|
17
|
+
positions: definition.loc?.start ? [definition.loc.start] : undefined,
|
|
18
|
+
});
|
|
15
19
|
}
|
|
16
20
|
}
|
|
17
21
|
}
|
|
@@ -20,7 +20,11 @@ function validateQueryDepth({ source, doc, maxDepth, fragmentGraph, }) {
|
|
|
20
20
|
throw errorOrNode;
|
|
21
21
|
}
|
|
22
22
|
const node = errorOrNode;
|
|
23
|
-
return new graphql_1.GraphQLError(`Query exceeds maximum depth of ${maxDepth}`,
|
|
23
|
+
return new graphql_1.GraphQLError(`Query exceeds maximum depth of ${maxDepth}`, {
|
|
24
|
+
nodes: node,
|
|
25
|
+
source,
|
|
26
|
+
positions: node.loc?.start ? [node.loc.start] : undefined,
|
|
27
|
+
});
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
30
|
function calculateDepth({ node, currentDepth, maxDepth, getFragment, }) {
|
|
@@ -48,6 +48,10 @@ function calculateTokenCount(args) {
|
|
|
48
48
|
function validateTokenCount(args) {
|
|
49
49
|
const tokenCount = calculateTokenCount(args);
|
|
50
50
|
if (tokenCount > args.maxTokenCount) {
|
|
51
|
-
return new graphql_1.GraphQLError(`Query exceeds maximum token count of ${args.maxTokenCount} (actual: ${tokenCount})`,
|
|
51
|
+
return new graphql_1.GraphQLError(`Query exceeds maximum token count of ${args.maxTokenCount} (actual: ${tokenCount})`, {
|
|
52
|
+
nodes: args.document,
|
|
53
|
+
source: args.source,
|
|
54
|
+
positions: args.document.loc?.start ? [args.document.loc.start] : undefined,
|
|
55
|
+
});
|
|
52
56
|
}
|
|
53
57
|
}
|
package/cjs/run.js
CHANGED
|
@@ -31,6 +31,10 @@ async function run() {
|
|
|
31
31
|
}
|
|
32
32
|
const useMerge = (0, utils_js_2.castToBoolean)(core.getInput('experimental_merge'), true);
|
|
33
33
|
const useAnnotations = (0, utils_js_2.castToBoolean)(core.getInput('annotations'));
|
|
34
|
+
const annotationLevel = core.getInput('annotation-level') || types_js_1.AnnotationFilterLevel.All;
|
|
35
|
+
if (!(0, utils_js_2.isAnnotationFilterLevel)(annotationLevel)) {
|
|
36
|
+
return core.setFailed(`Invalid annotation-level. Expected one of: ${Object.values(types_js_1.AnnotationFilterLevel).join(', ')}.`);
|
|
37
|
+
}
|
|
34
38
|
const failOnBreaking = (0, utils_js_2.castToBoolean)(core.getInput('fail-on-breaking'));
|
|
35
39
|
const endpoint = core.getInput('endpoint');
|
|
36
40
|
const approveLabel = core.getInput('approve-label') || 'approved-breaking-change';
|
|
@@ -76,7 +80,11 @@ async function run() {
|
|
|
76
80
|
}
|
|
77
81
|
let config;
|
|
78
82
|
if (onUsage) {
|
|
79
|
-
|
|
83
|
+
// real runtime require so ncc doesn't try to resolve it from the bundle
|
|
84
|
+
const checkUsage = process
|
|
85
|
+
// @ts-expect-error getBuiltinModule exists starting node v20.16.0
|
|
86
|
+
.getBuiltinModule('module')
|
|
87
|
+
.createRequire(import.meta.url)(onUsage);
|
|
80
88
|
if (checkUsage) {
|
|
81
89
|
config = {
|
|
82
90
|
checkUsage,
|
|
@@ -162,6 +170,11 @@ async function run() {
|
|
|
162
170
|
core.info(`Anotations are disabled. Skipping annotations...`);
|
|
163
171
|
annotations = [];
|
|
164
172
|
}
|
|
173
|
+
else if (annotationLevel !== types_js_1.AnnotationFilterLevel.All) {
|
|
174
|
+
annotations = annotations.filter(annotation => annotationLevel === types_js_1.AnnotationFilterLevel.Breaking
|
|
175
|
+
? annotation.annotation_level === types_js_1.AnnotationLevel.Failure
|
|
176
|
+
: annotation.annotation_level !== types_js_1.AnnotationLevel.Notice);
|
|
177
|
+
}
|
|
165
178
|
const summary = (0, utils_js_1.createSummary)(changes, 100, false);
|
|
166
179
|
const title = conclusion === types_js_1.CheckConclusion.Failure
|
|
167
180
|
? 'Something is wrong with your schema'
|
package/cjs/utils.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.batch = batch;
|
|
4
4
|
exports.castToBoolean = castToBoolean;
|
|
5
|
+
exports.isAnnotationFilterLevel = isAnnotationFilterLevel;
|
|
5
6
|
exports.getInputAsArray = getInputAsArray;
|
|
6
7
|
exports.resolveRule = resolveRule;
|
|
7
8
|
const tslib_1 = require("tslib");
|
|
@@ -9,6 +10,8 @@ const fs_1 = require("fs");
|
|
|
9
10
|
const core = tslib_1.__importStar(require("@actions/core"));
|
|
10
11
|
const commands_1 = require("@graphql-inspector/commands");
|
|
11
12
|
const core_1 = require("@graphql-inspector/core");
|
|
13
|
+
const types_js_1 = require("../helpers/types.js");
|
|
14
|
+
const annotationFilterLevels = Object.values(types_js_1.AnnotationFilterLevel);
|
|
12
15
|
function batch(items, limit) {
|
|
13
16
|
const batches = [];
|
|
14
17
|
const batchesNum = Math.ceil(items.length / limit);
|
|
@@ -38,6 +41,9 @@ function castToBoolean(value, defaultValue) {
|
|
|
38
41
|
}
|
|
39
42
|
return true;
|
|
40
43
|
}
|
|
44
|
+
function isAnnotationFilterLevel(value) {
|
|
45
|
+
return annotationFilterLevels.includes(value);
|
|
46
|
+
}
|
|
41
47
|
function getInputAsArray(name, options) {
|
|
42
48
|
return core
|
|
43
49
|
.getInput(name, options)
|
|
@@ -48,7 +54,12 @@ function getInputAsArray(name, options) {
|
|
|
48
54
|
function resolveRule(name) {
|
|
49
55
|
const filepath = (0, commands_1.ensureAbsolute)(name);
|
|
50
56
|
if ((0, fs_1.existsSync)(filepath)) {
|
|
51
|
-
|
|
57
|
+
// ncc rewrites bare require to its bundler require, which can't load files
|
|
58
|
+
// outside the bundle. createRequire gives us a real runtime require.
|
|
59
|
+
return (process
|
|
60
|
+
// @ts-expect-error getBuiltinModule exists starting node v20.16.0
|
|
61
|
+
.getBuiltinModule('module')
|
|
62
|
+
.createRequire(import.meta.url)(filepath));
|
|
52
63
|
}
|
|
53
64
|
return core_1.DiffRule[name];
|
|
54
65
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export var AnnotationFilterLevel;
|
|
2
|
+
(function (AnnotationFilterLevel) {
|
|
3
|
+
AnnotationFilterLevel["All"] = "all";
|
|
4
|
+
AnnotationFilterLevel["Dangerous"] = "dangerous";
|
|
5
|
+
AnnotationFilterLevel["Breaking"] = "breaking";
|
|
6
|
+
})(AnnotationFilterLevel || (AnnotationFilterLevel = {}));
|
|
1
7
|
export var AnnotationLevel;
|
|
2
8
|
(function (AnnotationLevel) {
|
|
3
9
|
AnnotationLevel["Failure"] = "failure";
|
package/esm/action/src/run.js
CHANGED
|
@@ -5,12 +5,12 @@ import * as github from '@actions/github';
|
|
|
5
5
|
import { diff } from '../helpers/diff.js';
|
|
6
6
|
import { printSchemaFromEndpoint } from '../helpers/loaders.js';
|
|
7
7
|
import { produceSchema } from '../helpers/schema.js';
|
|
8
|
-
import { CheckConclusion } from '../helpers/types.js';
|
|
8
|
+
import { AnnotationFilterLevel, AnnotationLevel, CheckConclusion } from '../helpers/types.js';
|
|
9
9
|
import { createSummary } from '../helpers/utils.js';
|
|
10
10
|
import { updateCheckRun } from './checks.js';
|
|
11
11
|
import { fileLoader } from './files.js';
|
|
12
12
|
import { getAssociatedPullRequest, getCurrentCommitSha } from './git.js';
|
|
13
|
-
import { castToBoolean, getInputAsArray, resolveRule } from './utils.js';
|
|
13
|
+
import { castToBoolean, getInputAsArray, isAnnotationFilterLevel, resolveRule } from './utils.js';
|
|
14
14
|
const CHECK_NAME = 'GraphQL Inspector';
|
|
15
15
|
export async function run() {
|
|
16
16
|
core.info(`GraphQL Inspector started`);
|
|
@@ -27,6 +27,10 @@ export async function run() {
|
|
|
27
27
|
}
|
|
28
28
|
const useMerge = castToBoolean(core.getInput('experimental_merge'), true);
|
|
29
29
|
const useAnnotations = castToBoolean(core.getInput('annotations'));
|
|
30
|
+
const annotationLevel = core.getInput('annotation-level') || AnnotationFilterLevel.All;
|
|
31
|
+
if (!isAnnotationFilterLevel(annotationLevel)) {
|
|
32
|
+
return core.setFailed(`Invalid annotation-level. Expected one of: ${Object.values(AnnotationFilterLevel).join(', ')}.`);
|
|
33
|
+
}
|
|
30
34
|
const failOnBreaking = castToBoolean(core.getInput('fail-on-breaking'));
|
|
31
35
|
const endpoint = core.getInput('endpoint');
|
|
32
36
|
const approveLabel = core.getInput('approve-label') || 'approved-breaking-change';
|
|
@@ -72,7 +76,11 @@ export async function run() {
|
|
|
72
76
|
}
|
|
73
77
|
let config;
|
|
74
78
|
if (onUsage) {
|
|
75
|
-
|
|
79
|
+
// real runtime require so ncc doesn't try to resolve it from the bundle
|
|
80
|
+
const checkUsage = process
|
|
81
|
+
// @ts-expect-error getBuiltinModule exists starting node v20.16.0
|
|
82
|
+
.getBuiltinModule('module')
|
|
83
|
+
.createRequire(import.meta.url)(onUsage);
|
|
76
84
|
if (checkUsage) {
|
|
77
85
|
config = {
|
|
78
86
|
checkUsage,
|
|
@@ -158,6 +166,11 @@ export async function run() {
|
|
|
158
166
|
core.info(`Anotations are disabled. Skipping annotations...`);
|
|
159
167
|
annotations = [];
|
|
160
168
|
}
|
|
169
|
+
else if (annotationLevel !== AnnotationFilterLevel.All) {
|
|
170
|
+
annotations = annotations.filter(annotation => annotationLevel === AnnotationFilterLevel.Breaking
|
|
171
|
+
? annotation.annotation_level === AnnotationLevel.Failure
|
|
172
|
+
: annotation.annotation_level !== AnnotationLevel.Notice);
|
|
173
|
+
}
|
|
161
174
|
const summary = createSummary(changes, 100, false);
|
|
162
175
|
const title = conclusion === CheckConclusion.Failure
|
|
163
176
|
? 'Something is wrong with your schema'
|
package/esm/action/src/utils.js
CHANGED
|
@@ -2,6 +2,8 @@ import { existsSync } from 'fs';
|
|
|
2
2
|
import * as core from '@actions/core';
|
|
3
3
|
import { ensureAbsolute } from '@graphql-inspector/commands';
|
|
4
4
|
import { DiffRule } from '@graphql-inspector/core';
|
|
5
|
+
import { AnnotationFilterLevel } from '../helpers/types.js';
|
|
6
|
+
const annotationFilterLevels = Object.values(AnnotationFilterLevel);
|
|
5
7
|
export function batch(items, limit) {
|
|
6
8
|
const batches = [];
|
|
7
9
|
const batchesNum = Math.ceil(items.length / limit);
|
|
@@ -31,6 +33,9 @@ export function castToBoolean(value, defaultValue) {
|
|
|
31
33
|
}
|
|
32
34
|
return true;
|
|
33
35
|
}
|
|
36
|
+
export function isAnnotationFilterLevel(value) {
|
|
37
|
+
return annotationFilterLevels.includes(value);
|
|
38
|
+
}
|
|
34
39
|
export function getInputAsArray(name, options) {
|
|
35
40
|
return core
|
|
36
41
|
.getInput(name, options)
|
|
@@ -41,7 +46,12 @@ export function getInputAsArray(name, options) {
|
|
|
41
46
|
export function resolveRule(name) {
|
|
42
47
|
const filepath = ensureAbsolute(name);
|
|
43
48
|
if (existsSync(filepath)) {
|
|
44
|
-
|
|
49
|
+
// ncc rewrites bare require to its bundler require, which can't load files
|
|
50
|
+
// outside the bundle. createRequire gives us a real runtime require.
|
|
51
|
+
return (process
|
|
52
|
+
// @ts-expect-error getBuiltinModule exists starting node v20.16.0
|
|
53
|
+
.getBuiltinModule('module')
|
|
54
|
+
.createRequire(import.meta.url)(filepath));
|
|
45
55
|
}
|
|
46
56
|
return DiffRule[name];
|
|
47
57
|
}
|
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
import { Kind, } from 'graphql';
|
|
2
|
-
import { compareDirectiveLists,
|
|
2
|
+
import { compareDirectiveLists, isNotEqual } from '../utils/compare.js';
|
|
3
|
+
import { defaultValuesAreEqual } from '../utils/graphql.js';
|
|
3
4
|
import { fieldArgumentDefaultChanged, fieldArgumentDescriptionChanged, fieldArgumentTypeChanged, } from './changes/argument.js';
|
|
4
5
|
import { directiveUsageAdded, directiveUsageChanged, directiveUsageRemoved, } from './changes/directive-usage.js';
|
|
5
6
|
export function changesInArgument(type, field, oldArg, newArg, addChange) {
|
|
6
7
|
if (isNotEqual(oldArg?.description, newArg.description)) {
|
|
7
8
|
addChange(fieldArgumentDescriptionChanged(type, field, oldArg, newArg));
|
|
8
9
|
}
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
const diff = diffArrays(oldArg.defaultValue, newArg.defaultValue);
|
|
12
|
-
if (diff.length > 0) {
|
|
13
|
-
addChange(fieldArgumentDefaultChanged(type, field, oldArg, newArg));
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
else if (JSON.stringify(oldArg?.defaultValue) !== JSON.stringify(newArg.defaultValue)) {
|
|
17
|
-
addChange(fieldArgumentDefaultChanged(type, field, oldArg, newArg));
|
|
18
|
-
}
|
|
10
|
+
if (!defaultValuesAreEqual(oldArg, newArg)) {
|
|
11
|
+
addChange(fieldArgumentDefaultChanged(type, field, oldArg, newArg));
|
|
19
12
|
}
|
|
20
13
|
if (isNotEqual(oldArg?.type.toString(), newArg.type.toString())) {
|
|
21
14
|
addChange(fieldArgumentTypeChanged(type, field, oldArg, newArg));
|
|
22
15
|
}
|
|
23
|
-
if (newArg.astNode?.directives) {
|
|
24
|
-
compareDirectiveLists(oldArg?.astNode?.directives || [], newArg.astNode
|
|
16
|
+
if (oldArg?.astNode?.directives || newArg.astNode?.directives) {
|
|
17
|
+
compareDirectiveLists(oldArg?.astNode?.directives || [], newArg.astNode?.directives || [], {
|
|
25
18
|
onAdded(directive) {
|
|
26
19
|
addChange(directiveUsageAdded(Kind.ARGUMENT, directive, {
|
|
27
20
|
argument: newArg,
|