@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,4 +1,4 @@
|
|
|
1
|
-
import { safeChangeForInputValue } from '../../utils/graphql.js';
|
|
1
|
+
import { getDefaultValue, safeChangeForInputValue } from '../../utils/graphql.js';
|
|
2
2
|
import { fmt, safeString } from '../../utils/string.js';
|
|
3
3
|
import { ChangeType, CriticalityLevel, } from './change.js';
|
|
4
4
|
function buildFieldArgumentDescriptionChangedMessage(args) {
|
|
@@ -57,11 +57,13 @@ export function fieldArgumentDefaultChanged(type, field, oldArg, newArg) {
|
|
|
57
57
|
fieldName: field.name,
|
|
58
58
|
argumentName: newArg.name,
|
|
59
59
|
};
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
const oldDefaultValue = oldArg === null ? undefined : getDefaultValue(oldArg);
|
|
61
|
+
const newDefaultValue = getDefaultValue(newArg);
|
|
62
|
+
if (oldDefaultValue !== undefined) {
|
|
63
|
+
meta.oldDefaultValue = safeString(oldDefaultValue);
|
|
62
64
|
}
|
|
63
|
-
if (
|
|
64
|
-
meta.newDefaultValue = safeString(
|
|
65
|
+
if (newDefaultValue !== undefined) {
|
|
66
|
+
meta.newDefaultValue = safeString(newDefaultValue);
|
|
65
67
|
}
|
|
66
68
|
return fieldArgumentDefaultChangedFromMeta({
|
|
67
69
|
type: ChangeType.FieldArgumentDefaultChanged,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNonNullType } from 'graphql';
|
|
2
|
-
import { safeChangeForInputValue } from '../../utils/graphql.js';
|
|
2
|
+
import { getDefaultValue, hasDefaultValue, safeChangeForInputValue } from '../../utils/graphql.js';
|
|
3
3
|
import { fmt, safeString } from '../../utils/string.js';
|
|
4
4
|
import { ChangeType, CriticalityLevel, } from './change.js';
|
|
5
5
|
function buildDirectiveRemovedMessage(args) {
|
|
@@ -205,7 +205,9 @@ export function directiveArgumentAdded(directive, arg, addedToNewDirective) {
|
|
|
205
205
|
directiveName: directive.name,
|
|
206
206
|
addedDirectiveArgumentName: arg.name,
|
|
207
207
|
addedDirectiveArgumentType: arg.type.toString(),
|
|
208
|
-
addedDirectiveDefaultValue:
|
|
208
|
+
addedDirectiveDefaultValue: hasDefaultValue(arg)
|
|
209
|
+
? safeString(getDefaultValue(arg))
|
|
210
|
+
: undefined,
|
|
209
211
|
addedDirectiveArgumentTypeIsNonNull: isNonNullType(arg.type),
|
|
210
212
|
addedDirectiveArgumentDescription: arg.description ?? undefined,
|
|
211
213
|
addedToNewDirective,
|
|
@@ -293,11 +295,13 @@ export function directiveArgumentDefaultValueChanged(directive, oldArg, newArg)
|
|
|
293
295
|
directiveName: directive.name,
|
|
294
296
|
directiveArgumentName: newArg.name,
|
|
295
297
|
};
|
|
296
|
-
|
|
297
|
-
|
|
298
|
+
const oldDefaultValue = oldArg === null ? undefined : getDefaultValue(oldArg);
|
|
299
|
+
const newDefaultValue = getDefaultValue(newArg);
|
|
300
|
+
if (oldDefaultValue !== undefined) {
|
|
301
|
+
meta.oldDirectiveArgumentDefaultValue = safeString(oldDefaultValue);
|
|
298
302
|
}
|
|
299
|
-
if (
|
|
300
|
-
meta.newDirectiveArgumentDefaultValue = safeString(
|
|
303
|
+
if (newDefaultValue !== undefined) {
|
|
304
|
+
meta.newDirectiveArgumentDefaultValue = safeString(newDefaultValue);
|
|
301
305
|
}
|
|
302
306
|
return directiveArgumentDefaultValueChangedFromMeta({
|
|
303
307
|
type: ChangeType.DirectiveArgumentDefaultValueChanged,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GraphQLDeprecatedDirective, isInterfaceType, isNonNullType, } from 'graphql';
|
|
2
|
-
import { safeChangeForField } from '../../utils/graphql.js';
|
|
2
|
+
import { hasDefaultValue, safeChangeForField } from '../../utils/graphql.js';
|
|
3
3
|
import { fmt } from '../../utils/string.js';
|
|
4
4
|
import { ChangeType, CriticalityLevel, } from './change.js';
|
|
5
5
|
function buildFieldRemovedMessage(args) {
|
|
@@ -299,7 +299,8 @@ export function fieldArgumentAddedFromMeta(args) {
|
|
|
299
299
|
};
|
|
300
300
|
}
|
|
301
301
|
export function fieldArgumentAdded(type, field, arg, addedToNewField) {
|
|
302
|
-
const
|
|
302
|
+
const hasDefault = hasDefaultValue(arg);
|
|
303
|
+
const isBreaking = isNonNullType(arg.type) && !hasDefault;
|
|
303
304
|
return fieldArgumentAddedFromMeta({
|
|
304
305
|
type: ChangeType.FieldArgumentAdded,
|
|
305
306
|
meta: {
|
|
@@ -307,7 +308,7 @@ export function fieldArgumentAdded(type, field, arg, addedToNewField) {
|
|
|
307
308
|
fieldName: field.name,
|
|
308
309
|
addedArgumentName: arg.name,
|
|
309
310
|
addedArgumentType: arg.type.toString(),
|
|
310
|
-
hasDefaultValue:
|
|
311
|
+
hasDefaultValue: hasDefault,
|
|
311
312
|
addedToNewField,
|
|
312
313
|
isAddedFieldArgumentBreaking: isBreaking,
|
|
313
314
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNonNullType } from 'graphql';
|
|
2
|
-
import { safeChangeForInputValue } from '../../utils/graphql.js';
|
|
2
|
+
import { getDefaultValue, hasDefaultValue, safeChangeForInputValue } from '../../utils/graphql.js';
|
|
3
3
|
import { isDeprecated } from '../../utils/is-deprecated.js';
|
|
4
4
|
import { fmt, safeString } from '../../utils/string.js';
|
|
5
5
|
import { ChangeType, CriticalityLevel, } from './change.js';
|
|
@@ -67,6 +67,7 @@ export function inputFieldAddedFromMeta(args) {
|
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
export function inputFieldAdded(input, field, addedToNewType) {
|
|
70
|
+
const defaultValue = getDefaultValue(field);
|
|
70
71
|
return inputFieldAddedFromMeta({
|
|
71
72
|
type: ChangeType.InputFieldAdded,
|
|
72
73
|
meta: {
|
|
@@ -74,9 +75,7 @@ export function inputFieldAdded(input, field, addedToNewType) {
|
|
|
74
75
|
addedInputFieldName: field.name,
|
|
75
76
|
isAddedInputFieldTypeNullable: !isNonNullType(field.type),
|
|
76
77
|
addedInputFieldType: field.type.toString(),
|
|
77
|
-
...(field
|
|
78
|
-
? {}
|
|
79
|
-
: { addedFieldDefault: safeString(field.defaultValue) }),
|
|
78
|
+
...(hasDefaultValue(field) ? { addedFieldDefault: safeString(defaultValue) } : {}),
|
|
80
79
|
addedToNewType,
|
|
81
80
|
},
|
|
82
81
|
});
|
|
@@ -179,11 +178,13 @@ export function inputFieldDefaultValueChanged(input, oldField, newField) {
|
|
|
179
178
|
inputName: input.name,
|
|
180
179
|
inputFieldName: newField.name,
|
|
181
180
|
};
|
|
182
|
-
|
|
183
|
-
|
|
181
|
+
const oldDefaultValue = getDefaultValue(oldField);
|
|
182
|
+
const newDefaultValue = getDefaultValue(newField);
|
|
183
|
+
if (oldDefaultValue !== undefined) {
|
|
184
|
+
meta.oldDefaultValue = safeString(oldDefaultValue);
|
|
184
185
|
}
|
|
185
|
-
if (
|
|
186
|
-
meta.newDefaultValue = safeString(
|
|
186
|
+
if (newDefaultValue !== undefined) {
|
|
187
|
+
meta.newDefaultValue = safeString(newDefaultValue);
|
|
187
188
|
}
|
|
188
189
|
return inputFieldDefaultValueChangedFromMeta({
|
|
189
190
|
type: ChangeType.InputFieldDefaultValueChanged,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { compareLists, diffArrays, isNotEqual } from '../utils/compare.js';
|
|
2
|
+
import { defaultValuesAreEqual } from '../utils/graphql.js';
|
|
2
3
|
import { directiveArgumentAdded, directiveArgumentDefaultValueChanged, directiveArgumentDescriptionChanged, directiveArgumentRemoved, directiveArgumentTypeChanged, directiveDescriptionChanged, directiveLocationAdded, directiveLocationRemoved, directiveRepeatableAdded, directiveRepeatableRemoved, } from './changes/directive.js';
|
|
3
4
|
export function changesInDirective(oldDirective, newDirective, addChange) {
|
|
4
5
|
if (isNotEqual(oldDirective?.description, newDirective.description)) {
|
|
@@ -38,7 +39,7 @@ function changesInDirectiveArgument(directive, oldArg, newArg, addChange) {
|
|
|
38
39
|
if (isNotEqual(oldArg?.description, newArg.description)) {
|
|
39
40
|
addChange(directiveArgumentDescriptionChanged(directive, oldArg, newArg));
|
|
40
41
|
}
|
|
41
|
-
if (
|
|
42
|
+
if (!defaultValuesAreEqual(oldArg, newArg)) {
|
|
42
43
|
addChange(directiveArgumentDefaultValueChanged(directive, oldArg, newArg));
|
|
43
44
|
}
|
|
44
45
|
if (isNotEqual(oldArg.type.toString(), newArg.type.toString())) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Kind } from 'graphql';
|
|
2
|
-
import { compareDirectiveLists, compareLists,
|
|
2
|
+
import { compareDirectiveLists, compareLists, isNotEqual, isVoid } from '../utils/compare.js';
|
|
3
|
+
import { defaultValuesAreEqual } from '../utils/graphql.js';
|
|
3
4
|
import { directiveUsageAdded, directiveUsageChanged, directiveUsageRemoved, } from './changes/directive-usage.js';
|
|
4
5
|
import { inputFieldAdded, inputFieldDefaultValueChanged, inputFieldDescriptionAdded, inputFieldDescriptionChanged, inputFieldDescriptionRemoved, inputFieldRemoved, inputFieldTypeChanged, } from './changes/input.js';
|
|
5
6
|
export function changesInInputObject(oldInput, newInput, addChange) {
|
|
@@ -43,22 +44,15 @@ function changesInInputField(input, oldField, newField, addChange) {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
if (!isVoid(oldField)) {
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
if (diffArrays(oldField.defaultValue, newField.defaultValue).length > 0) {
|
|
49
|
-
addChange(inputFieldDefaultValueChanged(input, oldField, newField));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
else if (JSON.stringify(oldField?.defaultValue) !== JSON.stringify(newField.defaultValue)) {
|
|
53
|
-
addChange(inputFieldDefaultValueChanged(input, oldField, newField));
|
|
54
|
-
}
|
|
47
|
+
if (!defaultValuesAreEqual(oldField, newField)) {
|
|
48
|
+
addChange(inputFieldDefaultValueChanged(input, oldField, newField));
|
|
55
49
|
}
|
|
56
50
|
if (!isVoid(oldField) && isNotEqual(oldField.type.toString(), newField.type.toString())) {
|
|
57
51
|
addChange(inputFieldTypeChanged(input, oldField, newField));
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
|
-
if (newField.astNode?.directives) {
|
|
61
|
-
compareDirectiveLists(oldField?.astNode?.directives || [], newField.astNode
|
|
54
|
+
if (oldField?.astNode?.directives || newField.astNode?.directives) {
|
|
55
|
+
compareDirectiveLists(oldField?.astNode?.directives || [], newField.astNode?.directives || [], {
|
|
62
56
|
onAdded(directive) {
|
|
63
57
|
addChange(directiveUsageAdded(Kind.INPUT_VALUE_DEFINITION, directive, {
|
|
64
58
|
type: input,
|
|
@@ -1,5 +1,42 @@
|
|
|
1
|
-
import { getNamedType, GraphQLError, isInputObjectType, isInterfaceType, isListType, isNonNullType, isObjectType, isScalarType, isUnionType, isWrappingType, Kind, TypeInfo, visit, visitWithTypeInfo, } from 'graphql';
|
|
1
|
+
import { coerceInputValue, getNamedType, GraphQLError, isInputObjectType, isInterfaceType, isListType, isNonNullType, isObjectType, isScalarType, isUnionType, isWrappingType, Kind, TypeInfo, valueFromAST, visit, visitWithTypeInfo, } from 'graphql';
|
|
2
2
|
import { isDeprecated } from './is-deprecated.js';
|
|
3
|
+
export function getDefaultValue(inputValue) {
|
|
4
|
+
if (inputValue.default !== undefined) {
|
|
5
|
+
if (inputValue.default.literal !== undefined) {
|
|
6
|
+
return valueFromAST(inputValue.default.literal, inputValue.type);
|
|
7
|
+
}
|
|
8
|
+
return coerceInputValue(inputValue.default.value, inputValue.type);
|
|
9
|
+
}
|
|
10
|
+
return inputValue.defaultValue;
|
|
11
|
+
}
|
|
12
|
+
export function hasDefaultValue(inputValue) {
|
|
13
|
+
return inputValue.default !== undefined || inputValue.defaultValue !== undefined;
|
|
14
|
+
}
|
|
15
|
+
export function defaultValuesAreEqual(oldInputValue, newInputValue) {
|
|
16
|
+
return defaultValueEquals(oldInputValue == null ? undefined : getDefaultValue(oldInputValue), getDefaultValue(newInputValue));
|
|
17
|
+
}
|
|
18
|
+
function defaultValueEquals(oldValue, newValue) {
|
|
19
|
+
if (Object.is(oldValue, newValue)) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(oldValue) && Array.isArray(newValue)) {
|
|
23
|
+
return (oldValue.length === newValue.length &&
|
|
24
|
+
oldValue.every((value, index) => defaultValueEquals(value, newValue[index])));
|
|
25
|
+
}
|
|
26
|
+
if (oldValue !== null &&
|
|
27
|
+
newValue !== null &&
|
|
28
|
+
typeof oldValue === 'object' &&
|
|
29
|
+
typeof newValue === 'object') {
|
|
30
|
+
const oldRecord = oldValue;
|
|
31
|
+
const newRecord = newValue;
|
|
32
|
+
const oldKeys = Object.keys(oldRecord);
|
|
33
|
+
const newKeys = Object.keys(newRecord);
|
|
34
|
+
return (oldKeys.length === newKeys.length &&
|
|
35
|
+
oldKeys.every(key => Object.prototype.hasOwnProperty.call(newRecord, key) &&
|
|
36
|
+
defaultValueEquals(oldRecord[key], newRecord[key])));
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
3
40
|
export function safeChangeForField(oldType, newType) {
|
|
4
41
|
if (!isWrappingType(oldType) && !isWrappingType(newType)) {
|
|
5
42
|
return oldType.toString() === newType.toString();
|
|
@@ -69,7 +106,7 @@ export function findDeprecatedUsages(schema, ast) {
|
|
|
69
106
|
if (reason) {
|
|
70
107
|
const fieldDef = typeInfo.getFieldDef();
|
|
71
108
|
if (fieldDef) {
|
|
72
|
-
errors.push(new GraphQLError(`The argument '${argument?.name}' of '${fieldDef.name}' is deprecated. ${reason}`, [node]));
|
|
109
|
+
errors.push(new GraphQLError(`The argument '${argument?.name}' of '${fieldDef.name}' is deprecated. ${reason}`, { nodes: [node] }));
|
|
73
110
|
}
|
|
74
111
|
}
|
|
75
112
|
}
|
|
@@ -80,7 +117,7 @@ export function findDeprecatedUsages(schema, ast) {
|
|
|
80
117
|
const parentType = typeInfo.getParentType();
|
|
81
118
|
if (parentType) {
|
|
82
119
|
const reason = fieldDef.deprecationReason;
|
|
83
|
-
errors.push(new GraphQLError(`The field '${parentType.name}.${fieldDef.name}' is deprecated.${reason ? ' ' + reason : ''}`, [node]));
|
|
120
|
+
errors.push(new GraphQLError(`The field '${parentType.name}.${fieldDef.name}' is deprecated.${reason ? ' ' + reason : ''}`, { nodes: [node] }));
|
|
84
121
|
}
|
|
85
122
|
}
|
|
86
123
|
},
|
|
@@ -90,7 +127,7 @@ export function findDeprecatedUsages(schema, ast) {
|
|
|
90
127
|
const type = getNamedType(typeInfo.getInputType());
|
|
91
128
|
if (type) {
|
|
92
129
|
const reason = enumVal.deprecationReason;
|
|
93
|
-
errors.push(new GraphQLError(`The enum value '${type.name}.${enumVal.name}' is deprecated.${reason ? ' ' + reason : ''}`, [node]));
|
|
130
|
+
errors.push(new GraphQLError(`The enum value '${type.name}.${enumVal.name}' is deprecated.${reason ? ' ' + reason : ''}`, { nodes: [node] }));
|
|
94
131
|
}
|
|
95
132
|
}
|
|
96
133
|
},
|
|
@@ -7,7 +7,11 @@ export function validateAliasCount({ source, doc, maxAliasCount, fragmentGraph,
|
|
|
7
7
|
}
|
|
8
8
|
const aliasCount = countAliases(definition, getFragmentByFragmentName);
|
|
9
9
|
if (aliasCount > maxAliasCount) {
|
|
10
|
-
return new GraphQLError(`Too many aliases (${aliasCount}). Maximum allowed is ${maxAliasCount}`,
|
|
10
|
+
return new GraphQLError(`Too many aliases (${aliasCount}). Maximum allowed is ${maxAliasCount}`, {
|
|
11
|
+
source,
|
|
12
|
+
nodes: [definition],
|
|
13
|
+
positions: definition.loc?.start ? [definition.loc.start] : undefined,
|
|
14
|
+
});
|
|
11
15
|
}
|
|
12
16
|
}
|
|
13
17
|
}
|
|
@@ -7,7 +7,11 @@ export function validateComplexity({ source, doc, maxComplexityScore, config, fr
|
|
|
7
7
|
}
|
|
8
8
|
const complexityScore = calculateOperationComplexity(definition, config, getFragmentByFragmentName);
|
|
9
9
|
if (complexityScore > maxComplexityScore) {
|
|
10
|
-
return new GraphQLError(`Too high complexity score (${complexityScore}). Maximum allowed is ${maxComplexityScore}`,
|
|
10
|
+
return new GraphQLError(`Too high complexity score (${complexityScore}). Maximum allowed is ${maxComplexityScore}`, {
|
|
11
|
+
nodes: [definition],
|
|
12
|
+
positions: definition.loc?.start ? [definition.loc.start] : undefined,
|
|
13
|
+
source,
|
|
14
|
+
});
|
|
11
15
|
}
|
|
12
16
|
}
|
|
13
17
|
}
|
|
@@ -7,7 +7,11 @@ export function validateDirectiveCount({ source, doc, maxDirectiveCount, fragmen
|
|
|
7
7
|
}
|
|
8
8
|
const directiveCount = countDirectives(definition, getFragmentByFragmentName);
|
|
9
9
|
if (directiveCount > maxDirectiveCount) {
|
|
10
|
-
return new GraphQLError(`Too many directives (${directiveCount}). Maximum allowed is ${maxDirectiveCount}`,
|
|
10
|
+
return new GraphQLError(`Too many directives (${directiveCount}). Maximum allowed is ${maxDirectiveCount}`, {
|
|
11
|
+
nodes: [definition],
|
|
12
|
+
source,
|
|
13
|
+
positions: definition.loc?.start ? [definition.loc.start] : undefined,
|
|
14
|
+
});
|
|
11
15
|
}
|
|
12
16
|
}
|
|
13
17
|
}
|
|
@@ -15,7 +15,11 @@ export function validateQueryDepth({ source, doc, maxDepth, fragmentGraph, }) {
|
|
|
15
15
|
throw errorOrNode;
|
|
16
16
|
}
|
|
17
17
|
const node = errorOrNode;
|
|
18
|
-
return new GraphQLError(`Query exceeds maximum depth of ${maxDepth}`,
|
|
18
|
+
return new GraphQLError(`Query exceeds maximum depth of ${maxDepth}`, {
|
|
19
|
+
nodes: node,
|
|
20
|
+
source,
|
|
21
|
+
positions: node.loc?.start ? [node.loc.start] : undefined,
|
|
22
|
+
});
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
export function calculateDepth({ node, currentDepth, maxDepth, getFragment, }) {
|
|
@@ -44,6 +44,10 @@ export function calculateTokenCount(args) {
|
|
|
44
44
|
export function validateTokenCount(args) {
|
|
45
45
|
const tokenCount = calculateTokenCount(args);
|
|
46
46
|
if (tokenCount > args.maxTokenCount) {
|
|
47
|
-
return new GraphQLError(`Query exceeds maximum token count of ${args.maxTokenCount} (actual: ${tokenCount})`,
|
|
47
|
+
return new GraphQLError(`Query exceeds maximum token count of ${args.maxTokenCount} (actual: ${tokenCount})`, {
|
|
48
|
+
nodes: args.document,
|
|
49
|
+
source: args.source,
|
|
50
|
+
positions: args.document.loc?.start ? [args.document.loc.start] : undefined,
|
|
51
|
+
});
|
|
48
52
|
}
|
|
49
53
|
}
|
package/esm/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/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
|
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-inspector/action",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "GraphQL Inspector functionality for GitHub Actions",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@actions/core": "1.10.1",
|
|
8
|
-
"@actions/github": "6.0.0",
|
|
9
|
-
"dataloader": "2.2.2",
|
|
10
|
-
"js-yaml": "4.1.1",
|
|
11
|
-
"probot": "13.2.2",
|
|
12
|
-
"tslib": "2.6.2",
|
|
13
|
-
"@graphql-inspector/commands": "
|
|
14
|
-
"@graphql-inspector/core": "
|
|
7
|
+
"@actions/core": "^1.10.1",
|
|
8
|
+
"@actions/github": "^6.0.0",
|
|
9
|
+
"dataloader": "^2.2.2",
|
|
10
|
+
"js-yaml": "^4.1.1",
|
|
11
|
+
"probot": "^13.2.2",
|
|
12
|
+
"tslib": "~2.6.2",
|
|
13
|
+
"@graphql-inspector/commands": "^7.0.0",
|
|
14
|
+
"@graphql-inspector/core": "^8.0.0"
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "graphql-hive/graphql-inspector",
|
|
18
|
+
"url": "https://github.com/graphql-hive/graphql-inspector",
|
|
19
19
|
"directory": "packages/action"
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
@@ -16,6 +16,11 @@ export interface Annotation {
|
|
|
16
16
|
start_column?: number;
|
|
17
17
|
end_column?: number;
|
|
18
18
|
}
|
|
19
|
+
export declare enum AnnotationFilterLevel {
|
|
20
|
+
All = "all",
|
|
21
|
+
Dangerous = "dangerous",
|
|
22
|
+
Breaking = "breaking"
|
|
23
|
+
}
|
|
19
24
|
export declare enum AnnotationLevel {
|
|
20
25
|
Failure = "failure",
|
|
21
26
|
Warning = "warning",
|
|
@@ -16,6 +16,11 @@ export interface Annotation {
|
|
|
16
16
|
start_column?: number;
|
|
17
17
|
end_column?: number;
|
|
18
18
|
}
|
|
19
|
+
export declare enum AnnotationFilterLevel {
|
|
20
|
+
All = "all",
|
|
21
|
+
Dangerous = "dangerous",
|
|
22
|
+
Breaking = "breaking"
|
|
23
|
+
}
|
|
19
24
|
export declare enum AnnotationLevel {
|
|
20
25
|
Failure = "failure",
|
|
21
26
|
Warning = "warning",
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as core from '@actions/core';
|
|
2
2
|
import { Rule } from '@graphql-inspector/core';
|
|
3
|
+
import { AnnotationFilterLevel } from '../helpers/types.cjs';
|
|
3
4
|
export declare function batch<T>(items: T[], limit: number): T[][];
|
|
4
5
|
/**
|
|
5
6
|
* Treats non-falsy value as true
|
|
6
7
|
*/
|
|
7
8
|
export declare function castToBoolean(value: string | boolean, defaultValue?: boolean): boolean;
|
|
9
|
+
export declare function isAnnotationFilterLevel(value: string): value is AnnotationFilterLevel;
|
|
8
10
|
export declare function getInputAsArray(name: string, options?: core.InputOptions): string[];
|
|
9
11
|
export declare function resolveRule(name: string): Rule | undefined;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as core from '@actions/core';
|
|
2
2
|
import { Rule } from '@graphql-inspector/core';
|
|
3
|
+
import { AnnotationFilterLevel } from '../helpers/types.js';
|
|
3
4
|
export declare function batch<T>(items: T[], limit: number): T[][];
|
|
4
5
|
/**
|
|
5
6
|
* Treats non-falsy value as true
|
|
6
7
|
*/
|
|
7
8
|
export declare function castToBoolean(value: string | boolean, defaultValue?: boolean): boolean;
|
|
9
|
+
export declare function isAnnotationFilterLevel(value: string): value is AnnotationFilterLevel;
|
|
8
10
|
export declare function getInputAsArray(name: string, options?: core.InputOptions): string[];
|
|
9
11
|
export declare function resolveRule(name: string): Rule | undefined;
|
|
@@ -524,7 +524,7 @@ type InputAddedMeta = TypeAddedMeta<Kind.INPUT_OBJECT_TYPE_DEFINITION> & {
|
|
|
524
524
|
};
|
|
525
525
|
export type TypeAddedChange = {
|
|
526
526
|
type: typeof ChangeType.TypeAdded;
|
|
527
|
-
meta: InputAddedMeta | TypeAddedMeta<Kind.ENUM_TYPE_DEFINITION | Kind.OBJECT_TYPE_DEFINITION | Kind.INTERFACE_TYPE_DEFINITION | Kind.UNION_TYPE_DEFINITION | Kind.SCALAR_TYPE_DEFINITION>;
|
|
527
|
+
meta: InputAddedMeta | TypeAddedMeta<typeof Kind.ENUM_TYPE_DEFINITION | typeof Kind.OBJECT_TYPE_DEFINITION | typeof Kind.INTERFACE_TYPE_DEFINITION | typeof Kind.UNION_TYPE_DEFINITION | typeof Kind.SCALAR_TYPE_DEFINITION>;
|
|
528
528
|
};
|
|
529
529
|
export type TypeKindChangedChange = {
|
|
530
530
|
type: typeof ChangeType.TypeKindChanged;
|
|
@@ -524,7 +524,7 @@ type InputAddedMeta = TypeAddedMeta<Kind.INPUT_OBJECT_TYPE_DEFINITION> & {
|
|
|
524
524
|
};
|
|
525
525
|
export type TypeAddedChange = {
|
|
526
526
|
type: typeof ChangeType.TypeAdded;
|
|
527
|
-
meta: InputAddedMeta | TypeAddedMeta<Kind.ENUM_TYPE_DEFINITION | Kind.OBJECT_TYPE_DEFINITION | Kind.INTERFACE_TYPE_DEFINITION | Kind.UNION_TYPE_DEFINITION | Kind.SCALAR_TYPE_DEFINITION>;
|
|
527
|
+
meta: InputAddedMeta | TypeAddedMeta<typeof Kind.ENUM_TYPE_DEFINITION | typeof Kind.OBJECT_TYPE_DEFINITION | typeof Kind.INTERFACE_TYPE_DEFINITION | typeof Kind.UNION_TYPE_DEFINITION | typeof Kind.SCALAR_TYPE_DEFINITION>;
|
|
528
528
|
};
|
|
529
529
|
export type TypeKindChangedChange = {
|
|
530
530
|
type: typeof ChangeType.TypeKindChanged;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DirectiveLocation, GraphQLArgument, GraphQLDirective } from 'graphql';
|
|
2
2
|
import { Change, ChangeType, CriticalityLevel, DirectiveAddedChange, DirectiveArgumentAddedChange, DirectiveArgumentDefaultValueChangedChange, DirectiveArgumentDescriptionChangedChange, DirectiveArgumentRemovedChange, DirectiveArgumentTypeChangedChange, DirectiveDescriptionChangedChange, DirectiveLocationAddedChange, DirectiveLocationRemovedChange, DirectiveRemovedChange, DirectiveRepeatableAddedChange, DirectiveRepeatableRemovedChange } from './change.cjs';
|
|
3
3
|
export declare function directiveRemovedFromMeta(args: DirectiveRemovedChange): {
|
|
4
4
|
readonly criticality: {
|
|
@@ -58,7 +58,7 @@ export declare function directiveLocationAddedFromMeta(args: DirectiveLocationAd
|
|
|
58
58
|
addedDirectiveLocation: string;
|
|
59
59
|
};
|
|
60
60
|
};
|
|
61
|
-
export declare function directiveLocationAdded(directive: GraphQLDirective, location:
|
|
61
|
+
export declare function directiveLocationAdded(directive: GraphQLDirective, location: DirectiveLocation): Change<typeof ChangeType.DirectiveLocationAdded>;
|
|
62
62
|
export declare function directiveLocationRemovedFromMeta(args: DirectiveLocationRemovedChange): {
|
|
63
63
|
readonly criticality: {
|
|
64
64
|
readonly level: CriticalityLevel.Breaking;
|
|
@@ -72,7 +72,7 @@ export declare function directiveLocationRemovedFromMeta(args: DirectiveLocation
|
|
|
72
72
|
removedDirectiveLocation: string;
|
|
73
73
|
};
|
|
74
74
|
};
|
|
75
|
-
export declare function directiveLocationRemoved(directive: GraphQLDirective, location:
|
|
75
|
+
export declare function directiveLocationRemoved(directive: GraphQLDirective, location: DirectiveLocation): Change<typeof ChangeType.DirectiveLocationRemoved>;
|
|
76
76
|
export declare function directiveArgumentAddedFromMeta(args: DirectiveArgumentAddedChange): {
|
|
77
77
|
readonly criticality: {
|
|
78
78
|
level: CriticalityLevel;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DirectiveLocation, GraphQLArgument, GraphQLDirective } from 'graphql';
|
|
2
2
|
import { Change, ChangeType, CriticalityLevel, DirectiveAddedChange, DirectiveArgumentAddedChange, DirectiveArgumentDefaultValueChangedChange, DirectiveArgumentDescriptionChangedChange, DirectiveArgumentRemovedChange, DirectiveArgumentTypeChangedChange, DirectiveDescriptionChangedChange, DirectiveLocationAddedChange, DirectiveLocationRemovedChange, DirectiveRemovedChange, DirectiveRepeatableAddedChange, DirectiveRepeatableRemovedChange } from './change.js';
|
|
3
3
|
export declare function directiveRemovedFromMeta(args: DirectiveRemovedChange): {
|
|
4
4
|
readonly criticality: {
|
|
@@ -58,7 +58,7 @@ export declare function directiveLocationAddedFromMeta(args: DirectiveLocationAd
|
|
|
58
58
|
addedDirectiveLocation: string;
|
|
59
59
|
};
|
|
60
60
|
};
|
|
61
|
-
export declare function directiveLocationAdded(directive: GraphQLDirective, location:
|
|
61
|
+
export declare function directiveLocationAdded(directive: GraphQLDirective, location: DirectiveLocation): Change<typeof ChangeType.DirectiveLocationAdded>;
|
|
62
62
|
export declare function directiveLocationRemovedFromMeta(args: DirectiveLocationRemovedChange): {
|
|
63
63
|
readonly criticality: {
|
|
64
64
|
readonly level: CriticalityLevel.Breaking;
|
|
@@ -72,7 +72,7 @@ export declare function directiveLocationRemovedFromMeta(args: DirectiveLocation
|
|
|
72
72
|
removedDirectiveLocation: string;
|
|
73
73
|
};
|
|
74
74
|
};
|
|
75
|
-
export declare function directiveLocationRemoved(directive: GraphQLDirective, location:
|
|
75
|
+
export declare function directiveLocationRemoved(directive: GraphQLDirective, location: DirectiveLocation): Change<typeof ChangeType.DirectiveLocationRemoved>;
|
|
76
76
|
export declare function directiveArgumentAddedFromMeta(args: DirectiveArgumentAddedChange): {
|
|
77
77
|
readonly criticality: {
|
|
78
78
|
level: CriticalityLevel;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type GraphQLNamedType } from 'graphql';
|
|
2
2
|
import { Change, ChangeType, CriticalityLevel, TypeAddedChange, TypeDescriptionAddedChange, TypeDescriptionChangedChange, TypeDescriptionRemovedChange, TypeKindChangedChange, TypeRemovedChange } from './change.cjs';
|
|
3
3
|
export declare function typeRemovedFromMeta(args: TypeRemovedChange): {
|
|
4
4
|
readonly criticality: {
|
|
@@ -20,12 +20,12 @@ export declare function typeAddedFromMeta(args: TypeAddedChange): {
|
|
|
20
20
|
readonly message: string;
|
|
21
21
|
readonly meta: ({
|
|
22
22
|
addedTypeName: string;
|
|
23
|
-
addedTypeKind:
|
|
23
|
+
addedTypeKind: "InputObjectTypeDefinition";
|
|
24
24
|
} & {
|
|
25
25
|
addedTypeIsOneOf: boolean;
|
|
26
26
|
}) | {
|
|
27
27
|
addedTypeName: string;
|
|
28
|
-
addedTypeKind:
|
|
28
|
+
addedTypeKind: "ScalarTypeDefinition" | "ObjectTypeDefinition" | "InterfaceTypeDefinition" | "UnionTypeDefinition" | "EnumTypeDefinition";
|
|
29
29
|
};
|
|
30
30
|
readonly path: string;
|
|
31
31
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type GraphQLNamedType } from 'graphql';
|
|
2
2
|
import { Change, ChangeType, CriticalityLevel, TypeAddedChange, TypeDescriptionAddedChange, TypeDescriptionChangedChange, TypeDescriptionRemovedChange, TypeKindChangedChange, TypeRemovedChange } from './change.js';
|
|
3
3
|
export declare function typeRemovedFromMeta(args: TypeRemovedChange): {
|
|
4
4
|
readonly criticality: {
|
|
@@ -20,12 +20,12 @@ export declare function typeAddedFromMeta(args: TypeAddedChange): {
|
|
|
20
20
|
readonly message: string;
|
|
21
21
|
readonly meta: ({
|
|
22
22
|
addedTypeName: string;
|
|
23
|
-
addedTypeKind:
|
|
23
|
+
addedTypeKind: "InputObjectTypeDefinition";
|
|
24
24
|
} & {
|
|
25
25
|
addedTypeIsOneOf: boolean;
|
|
26
26
|
}) | {
|
|
27
27
|
addedTypeName: string;
|
|
28
|
-
addedTypeKind:
|
|
28
|
+
addedTypeKind: "ScalarTypeDefinition" | "ObjectTypeDefinition" | "InterfaceTypeDefinition" | "UnionTypeDefinition" | "EnumTypeDefinition";
|
|
29
29
|
};
|
|
30
30
|
readonly path: string;
|
|
31
31
|
};
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
import { DocumentNode, FieldNode, GraphQLError, GraphQLInputType, GraphQLNamedType, GraphQLOutputType, GraphQLSchema,
|
|
1
|
+
import { ConstValueNode, DocumentNode, FieldNode, GraphQLArgument, GraphQLError, GraphQLInputField, GraphQLInputType, GraphQLNamedType, GraphQLOutputType, GraphQLSchema, Kind } from 'graphql';
|
|
2
|
+
type GraphQLInputValue = (GraphQLArgument | GraphQLInputField) & {
|
|
3
|
+
default?: {
|
|
4
|
+
literal: ConstValueNode;
|
|
5
|
+
value?: never;
|
|
6
|
+
} | {
|
|
7
|
+
value: unknown;
|
|
8
|
+
literal?: never;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export declare function getDefaultValue(inputValue: GraphQLInputValue): unknown;
|
|
12
|
+
export declare function hasDefaultValue(inputValue: GraphQLInputValue): boolean;
|
|
13
|
+
export declare function defaultValuesAreEqual(oldInputValue: GraphQLInputValue | null | undefined, newInputValue: GraphQLInputValue): boolean;
|
|
2
14
|
export declare function safeChangeForField(oldType: GraphQLOutputType, newType: GraphQLOutputType): boolean;
|
|
3
15
|
export declare function safeChangeForInputValue(oldType: GraphQLInputType, newType: GraphQLInputType): boolean;
|
|
4
|
-
export declare function getKind(type: GraphQLNamedType):
|
|
16
|
+
export declare function getKind(type: GraphQLNamedType): Kind;
|
|
5
17
|
export declare function getTypePrefix(type: GraphQLNamedType): string;
|
|
6
18
|
export declare function isPrimitive(type: GraphQLNamedType | string): boolean;
|
|
7
19
|
export declare function isForIntrospection(type: GraphQLNamedType | string): boolean;
|
|
@@ -9,3 +21,4 @@ export declare function findDeprecatedUsages(schema: GraphQLSchema, ast: Documen
|
|
|
9
21
|
export declare function removeFieldIfDirectives(node: FieldNode, directiveNames: string[]): FieldNode | null;
|
|
10
22
|
export declare function removeDirectives(node: FieldNode, directiveNames: string[]): FieldNode;
|
|
11
23
|
export declare function getReachableTypes(schema: GraphQLSchema): Set<string>;
|
|
24
|
+
export {};
|