@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.
Files changed (51) hide show
  1. package/cjs/action/helpers/types.js +7 -1
  2. package/cjs/action/src/run.js +14 -1
  3. package/cjs/action/src/utils.js +12 -1
  4. package/cjs/core/src/diff/argument.js +5 -12
  5. package/cjs/core/src/diff/changes/argument.js +6 -4
  6. package/cjs/core/src/diff/changes/directive.js +9 -5
  7. package/cjs/core/src/diff/changes/field.js +3 -2
  8. package/cjs/core/src/diff/changes/input.js +8 -7
  9. package/cjs/core/src/diff/directive.js +2 -1
  10. package/cjs/core/src/diff/input.js +5 -11
  11. package/cjs/core/src/utils/graphql.js +43 -3
  12. package/cjs/core/src/validate/alias-count.js +5 -1
  13. package/cjs/core/src/validate/complexity.js +5 -1
  14. package/cjs/core/src/validate/directive-count.js +5 -1
  15. package/cjs/core/src/validate/query-depth.js +5 -1
  16. package/cjs/core/src/validate/token-count.js +5 -1
  17. package/cjs/run.js +14 -1
  18. package/cjs/utils.js +12 -1
  19. package/esm/action/helpers/types.js +6 -0
  20. package/esm/action/src/run.js +16 -3
  21. package/esm/action/src/utils.js +11 -1
  22. package/esm/core/src/diff/argument.js +6 -13
  23. package/esm/core/src/diff/changes/argument.js +7 -5
  24. package/esm/core/src/diff/changes/directive.js +10 -6
  25. package/esm/core/src/diff/changes/field.js +4 -3
  26. package/esm/core/src/diff/changes/input.js +9 -8
  27. package/esm/core/src/diff/directive.js +2 -1
  28. package/esm/core/src/diff/input.js +6 -12
  29. package/esm/core/src/utils/graphql.js +41 -4
  30. package/esm/core/src/validate/alias-count.js +5 -1
  31. package/esm/core/src/validate/complexity.js +5 -1
  32. package/esm/core/src/validate/directive-count.js +5 -1
  33. package/esm/core/src/validate/query-depth.js +5 -1
  34. package/esm/core/src/validate/token-count.js +5 -1
  35. package/esm/run.js +16 -3
  36. package/esm/utils.js +11 -1
  37. package/package.json +10 -10
  38. package/typings/action/helpers/types.d.cts +5 -0
  39. package/typings/action/helpers/types.d.ts +5 -0
  40. package/typings/action/src/utils.d.cts +2 -0
  41. package/typings/action/src/utils.d.ts +2 -0
  42. package/typings/core/src/diff/changes/change.d.cts +1 -1
  43. package/typings/core/src/diff/changes/change.d.ts +1 -1
  44. package/typings/core/src/diff/changes/directive.d.cts +3 -3
  45. package/typings/core/src/diff/changes/directive.d.ts +3 -3
  46. package/typings/core/src/diff/changes/type.d.cts +3 -3
  47. package/typings/core/src/diff/changes/type.d.ts +3 -3
  48. package/typings/core/src/utils/graphql.d.cts +15 -2
  49. package/typings/core/src/utils/graphql.d.ts +15 -2
  50. package/typings/utils.d.cts +2 -0
  51. 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";
@@ -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
- const checkUsage = require(onUsage);
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'
@@ -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
- return require(filepath);
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, compare_js_1.isNotEqual)(oldArg?.defaultValue, newArg.defaultValue)) {
13
- if (Array.isArray(oldArg?.defaultValue) && Array.isArray(newArg.defaultValue)) {
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.directives || [], {
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
- if (oldArg?.defaultValue !== undefined) {
69
- meta.oldDefaultValue = (0, string_js_1.safeString)(oldArg.defaultValue);
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 (newArg.defaultValue !== undefined) {
72
- meta.newDefaultValue = (0, string_js_1.safeString)(newArg.defaultValue);
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: arg.defaultValue === undefined ? undefined : (0, string_js_1.safeString)(arg.defaultValue),
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
- if (oldArg?.defaultValue !== undefined) {
323
- meta.oldDirectiveArgumentDefaultValue = (0, string_js_1.safeString)(oldArg.defaultValue);
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 (newArg.defaultValue !== undefined) {
326
- meta.newDirectiveArgumentDefaultValue = (0, string_js_1.safeString)(newArg.defaultValue);
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 isBreaking = (0, graphql_1.isNonNullType)(arg.type) && typeof arg.defaultValue === 'undefined';
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: arg.defaultValue != null,
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 === undefined
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
- if (oldField.defaultValue !== undefined) {
200
- meta.oldDefaultValue = (0, string_js_1.safeString)(oldField.defaultValue);
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 (newField.defaultValue !== undefined) {
203
- meta.newDefaultValue = (0, string_js_1.safeString)(newField.defaultValue);
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, compare_js_1.isNotEqual)(oldArg?.defaultValue, newArg.defaultValue)) {
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, compare_js_1.isNotEqual)(oldField?.defaultValue, newField.defaultValue)) {
50
- if (Array.isArray(oldField?.defaultValue) && Array.isArray(newField.defaultValue)) {
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.directives || [], {
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}`, [definition], source, definition.loc?.start ? [definition.loc.start] : undefined);
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}`, [definition], source, definition.loc?.start ? [definition.loc.start] : undefined);
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}`, [definition], source, definition.loc?.start ? [definition.loc.start] : undefined);
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}`, node, source, node.loc?.start ? [node.loc.start] : undefined);
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})`, args.document, args.source, args.document.loc?.start ? [args.document.loc.start] : undefined);
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
- const checkUsage = require(onUsage);
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
- return require(filepath);
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";
@@ -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
- const checkUsage = require(onUsage);
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'
@@ -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
- return require(filepath);
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, diffArrays, isNotEqual } from '../utils/compare.js';
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 (isNotEqual(oldArg?.defaultValue, newArg.defaultValue)) {
10
- if (Array.isArray(oldArg?.defaultValue) && Array.isArray(newArg.defaultValue)) {
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.directives || [], {
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,