Skip to content

Commit 77a8473

Browse files
committed
added no-deprecated rule
1 parent 6687ac4 commit 77a8473

File tree

4 files changed

+72
-2
lines changed

4 files changed

+72
-2
lines changed

example/.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"rules": {
88
"@graphql-eslint/validate-against-schema": "error",
99
"@graphql-eslint/no-anonymous-operations": "error",
10-
"@graphql-eslint/no-operation-name-suffix": "error"
10+
"@graphql-eslint/no-operation-name-suffix": "error",
11+
"@graphql-eslint/deprecation-must-have-reason": "error"
1112
}
1213
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { GraphQLESLintRule, valueFromNode } from '@graphql-eslint/types';
2+
3+
const rule: GraphQLESLintRule = {
4+
meta: {},
5+
create(context) {
6+
return {
7+
Directive(node) {
8+
if (node && node.name && node.name.value === 'deprecated') {
9+
const args = node.arguments || [];
10+
const reasonArg = args.find(arg => arg.name && arg.name.value === 'reason');
11+
const value = reasonArg ? valueFromNode(reasonArg.value, {}) : null;
12+
13+
if (!value) {
14+
context.report({
15+
node: node.name,
16+
message: `Directive "@deprecated" must have a reason!`,
17+
});
18+
}
19+
}
20+
},
21+
}
22+
}
23+
}
24+
25+
export default rule;

packages/plugin/src/rules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import validate from "./validate-against-schema";
22
import noAnonymousOperations from "./no-anonymous-operations";
33
import noOperationNameSuffix from "./no-operation-name-suffix";
4+
import deprecationMustHaveReason from "./deprecation-must-have-reason";
45

56
export const rules = {
67
'validate-against-schema': validate,
78
'no-anonymous-operations': noAnonymousOperations,
89
'no-operation-name-suffix': noOperationNameSuffix,
10+
'deprecation-must-have-reason': deprecationMustHaveReason
911
};
1012

packages/types/src/utils.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { GraphQLESlintRuleContext } from "./rule";
2-
import { GraphQLSchema } from 'graphql';
2+
import { Kind, GraphQLSchema } from 'graphql';
3+
import { GraphQLESTree } from "./estree-ast";
34

45
export function requireGraphQLSchemaFromContext(
56
context: GraphQLESlintRuleContext
@@ -14,3 +15,44 @@ export function requireGraphQLSchemaFromContext(
1415

1516
return context.parserServices.schema;
1617
}
18+
19+
export default function keyValMap<T, V>(
20+
list: ReadonlyArray<T>,
21+
keyFn: (item: T) => string,
22+
valFn: (item: T) => V,
23+
): Record<string, V> {
24+
return list.reduce((map, item) => {
25+
map[keyFn(item)] = valFn(item);
26+
return map;
27+
}, Object.create(null));
28+
}
29+
30+
export function valueFromNode(
31+
valueNode: GraphQLESTree.ValueNode,
32+
variables?: Record<string, any>,
33+
): any {
34+
switch (valueNode.type) {
35+
case Kind.NULL:
36+
return null;
37+
case Kind.INT:
38+
return parseInt(valueNode.value, 10);
39+
case Kind.FLOAT:
40+
return parseFloat(valueNode.value);
41+
case Kind.STRING:
42+
case Kind.ENUM:
43+
case Kind.BOOLEAN:
44+
return valueNode.value;
45+
case Kind.LIST:
46+
return valueNode.values.map((node) =>
47+
valueFromNode(node, variables),
48+
);
49+
case Kind.OBJECT:
50+
return keyValMap(
51+
valueNode.fields,
52+
(field) => field.name.value,
53+
(field) => valueFromNode(field.value, variables),
54+
);
55+
case Kind.VARIABLE:
56+
return variables?.[valueNode.name.value];
57+
}
58+
}

0 commit comments

Comments
 (0)