@graphql-eslint/eslint-plugin 3.14.0-alpha-20221222204442-94bf749 â 3.14.0-alpha-20221222211346-788e7eb
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/configs/operations-all.js +1 -0
- package/cjs/rules/index.js +2 -0
- package/cjs/rules/no-one-place-fragments.js +84 -0
- package/docs/README.md +1 -0
- package/docs/rules/no-one-place-fragments.md +51 -0
- package/package.json +1 -1
- package/typings/configs/index.d.cts +1 -0
- package/typings/configs/index.d.ts +1 -0
- package/typings/configs/operations-all.d.cts +1 -0
- package/typings/configs/operations-all.d.ts +1 -0
- package/typings/rules/index.d.cts +1 -0
- package/typings/rules/index.d.ts +1 -0
- package/typings/rules/no-one-place-fragments.d.cts +2 -0
- package/typings/rules/no-one-place-fragments.d.ts +2 -0
package/cjs/rules/index.js
CHANGED
@@ -16,6 +16,7 @@ const no_case_insensitive_enum_values_duplicates_1 = require("./no-case-insensit
|
|
16
16
|
const no_deprecated_1 = require("./no-deprecated");
|
17
17
|
const no_duplicate_fields_1 = require("./no-duplicate-fields");
|
18
18
|
const no_hashtag_description_1 = require("./no-hashtag-description");
|
19
|
+
const no_one_place_fragments_1 = require("./no-one-place-fragments");
|
19
20
|
const no_root_type_1 = require("./no-root-type");
|
20
21
|
const no_scalar_result_type_on_mutation_1 = require("./no-scalar-result-type-on-mutation");
|
21
22
|
const no_typename_prefix_1 = require("./no-typename-prefix");
|
@@ -49,6 +50,7 @@ exports.rules = {
|
|
49
50
|
'no-deprecated': no_deprecated_1.rule,
|
50
51
|
'no-duplicate-fields': no_duplicate_fields_1.rule,
|
51
52
|
'no-hashtag-description': no_hashtag_description_1.rule,
|
53
|
+
'no-one-place-fragments': no_one_place_fragments_1.rule,
|
52
54
|
'no-root-type': no_root_type_1.rule,
|
53
55
|
'no-scalar-result-type-on-mutation': no_scalar_result_type_on_mutation_1.rule,
|
54
56
|
'no-typename-prefix': no_typename_prefix_1.rule,
|
@@ -0,0 +1,84 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.rule = void 0;
|
4
|
+
const eslint_plugin_1 = require("@graphql-eslint/eslint-plugin");
|
5
|
+
const utils_1 = require("../utils");
|
6
|
+
const path_1 = require("path");
|
7
|
+
const graphql_1 = require("graphql");
|
8
|
+
const RULE_ID = 'no-one-place-fragments';
|
9
|
+
exports.rule = {
|
10
|
+
meta: {
|
11
|
+
type: 'suggestion',
|
12
|
+
docs: {
|
13
|
+
category: 'Operations',
|
14
|
+
description: 'Disallow fragments that are used only in one place.',
|
15
|
+
url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`,
|
16
|
+
examples: [
|
17
|
+
{
|
18
|
+
title: 'Incorrect',
|
19
|
+
code: /* GraphQL */ `
|
20
|
+
fragment UserFields on User {
|
21
|
+
id
|
22
|
+
}
|
23
|
+
|
24
|
+
{
|
25
|
+
user {
|
26
|
+
...UserFields
|
27
|
+
friends {
|
28
|
+
...UserFields
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
`,
|
33
|
+
},
|
34
|
+
{
|
35
|
+
title: 'Correct',
|
36
|
+
code: /* GraphQL */ `
|
37
|
+
fragment UserFields on User {
|
38
|
+
id
|
39
|
+
}
|
40
|
+
|
41
|
+
{
|
42
|
+
user {
|
43
|
+
...UserFields
|
44
|
+
}
|
45
|
+
}
|
46
|
+
`,
|
47
|
+
},
|
48
|
+
],
|
49
|
+
requiresSiblings: true,
|
50
|
+
},
|
51
|
+
messages: {
|
52
|
+
[RULE_ID]: 'Fragment `{{fragmentName}}` used only once. Inline him in "{{filePath}}".',
|
53
|
+
},
|
54
|
+
schema: [],
|
55
|
+
},
|
56
|
+
create(context) {
|
57
|
+
const operations = (0, eslint_plugin_1.requireSiblingsOperations)(RULE_ID, context);
|
58
|
+
const allDocuments = [...operations.getOperations(), ...operations.getFragments()];
|
59
|
+
const usedFragmentsMap = Object.create(null);
|
60
|
+
for (const { document, filePath } of allDocuments) {
|
61
|
+
const relativeFilePath = (0, path_1.relative)(utils_1.CWD, filePath);
|
62
|
+
(0, graphql_1.visit)(document, {
|
63
|
+
FragmentSpread({ name }) {
|
64
|
+
const spreadName = name.value;
|
65
|
+
usedFragmentsMap[spreadName] || (usedFragmentsMap[spreadName] = []);
|
66
|
+
usedFragmentsMap[spreadName].push(relativeFilePath);
|
67
|
+
},
|
68
|
+
});
|
69
|
+
}
|
70
|
+
return {
|
71
|
+
'FragmentDefinition > Name'(node) {
|
72
|
+
const fragmentName = node.value;
|
73
|
+
const fragmentUsage = usedFragmentsMap[fragmentName];
|
74
|
+
if (fragmentUsage.length === 1) {
|
75
|
+
context.report({
|
76
|
+
node,
|
77
|
+
messageId: RULE_ID,
|
78
|
+
data: { fragmentName, filePath: fragmentUsage[0] },
|
79
|
+
});
|
80
|
+
}
|
81
|
+
},
|
82
|
+
};
|
83
|
+
},
|
84
|
+
};
|
package/docs/README.md
CHANGED
@@ -36,6 +36,7 @@ Name &nbs
|
|
36
36
|
[no-duplicate-fields](rules/no-duplicate-fields.md)|Checks for duplicate fields in selection set, variables in operation definition, or in arguments set of a field.|![recommended][]|đĻ|đ|đĄ
|
37
37
|
[no-fragment-cycles](rules/no-fragment-cycles.md)|A GraphQL fragment is only valid when it does not have cycles in fragments usage.|![recommended][]|đĻ|đŽ|
|
38
38
|
[no-hashtag-description](rules/no-hashtag-description.md)|Requires to use `"""` or `"` for adding a GraphQL description instead of `#`.|![recommended][]|đ|đ|đĄ
|
39
|
+
[no-one-place-fragments](rules/no-one-place-fragments.md)|Disallow fragments that are used only in one place.|![all][]|đĻ|đ|
|
39
40
|
[no-root-type](rules/no-root-type.md)|Disallow using root types `mutation` and/or `subscription`.||đ|đ|đĄ
|
40
41
|
[no-scalar-result-type-on-mutation](rules/no-scalar-result-type-on-mutation.md)|Avoid scalar result type on mutation type to make sure to return a valid state.|![all][]|đ|đ|đĄ
|
41
42
|
[no-typename-prefix](rules/no-typename-prefix.md)|Enforces users to avoid using the type name in a field name while defining your schema.|![recommended][]|đ|đ|đĄ
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# `no-one-place-fragments`
|
2
|
+
|
3
|
+
- Category: `Operations`
|
4
|
+
- Rule name: `@graphql-eslint/no-one-place-fragments`
|
5
|
+
- Requires GraphQL Schema: `false` [âšī¸](../../README.md#extended-linting-rules-with-graphql-schema)
|
6
|
+
- Requires GraphQL Operations: `true`
|
7
|
+
[âšī¸](../../README.md#extended-linting-rules-with-siblings-operations)
|
8
|
+
|
9
|
+
Disallow fragments that are used only in one place.
|
10
|
+
|
11
|
+
## Usage Examples
|
12
|
+
|
13
|
+
### Incorrect
|
14
|
+
|
15
|
+
```graphql
|
16
|
+
# eslint @graphql-eslint/no-one-place-fragments: 'error'
|
17
|
+
|
18
|
+
fragment UserFields on User {
|
19
|
+
id
|
20
|
+
}
|
21
|
+
|
22
|
+
{
|
23
|
+
user {
|
24
|
+
...UserFields
|
25
|
+
friends {
|
26
|
+
...UserFields
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
```
|
31
|
+
|
32
|
+
### Correct
|
33
|
+
|
34
|
+
```graphql
|
35
|
+
# eslint @graphql-eslint/no-one-place-fragments: 'error'
|
36
|
+
|
37
|
+
fragment UserFields on User {
|
38
|
+
id
|
39
|
+
}
|
40
|
+
|
41
|
+
{
|
42
|
+
user {
|
43
|
+
...UserFields
|
44
|
+
}
|
45
|
+
}
|
46
|
+
```
|
47
|
+
|
48
|
+
## Resources
|
49
|
+
|
50
|
+
- [Rule source](../../packages/plugin/src/rules/no-one-place-fragments.ts)
|
51
|
+
- [Test source](../../packages/plugin/tests/no-one-place-fragments.spec.ts)
|
package/package.json
CHANGED
@@ -125,6 +125,7 @@ export declare const configs: {
|
|
125
125
|
subscription: string;
|
126
126
|
fragment: string;
|
127
127
|
})[];
|
128
|
+
'@graphql-eslint/no-one-place-fragments': string;
|
128
129
|
'@graphql-eslint/unique-fragment-name': string;
|
129
130
|
'@graphql-eslint/unique-operation-name': string;
|
130
131
|
};
|
@@ -125,6 +125,7 @@ export declare const configs: {
|
|
125
125
|
subscription: string;
|
126
126
|
fragment: string;
|
127
127
|
})[];
|
128
|
+
'@graphql-eslint/no-one-place-fragments': string;
|
128
129
|
'@graphql-eslint/unique-fragment-name': string;
|
129
130
|
'@graphql-eslint/unique-operation-name': string;
|
130
131
|
};
|
@@ -61,6 +61,7 @@ export declare const rules: {
|
|
61
61
|
'no-deprecated': import("..").GraphQLESLintRule<[], true>;
|
62
62
|
'no-duplicate-fields': import("..").GraphQLESLintRule<any[], false>;
|
63
63
|
'no-hashtag-description': import("..").GraphQLESLintRule<any[], false>;
|
64
|
+
'no-one-place-fragments': import("..").GraphQLESLintRule<any[], false>;
|
64
65
|
'no-root-type': import("..").GraphQLESLintRule<{
|
65
66
|
disallow: ("mutation" | "subscription")[];
|
66
67
|
}[], false>;
|
package/typings/rules/index.d.ts
CHANGED
@@ -61,6 +61,7 @@ export declare const rules: {
|
|
61
61
|
'no-deprecated': import("..").GraphQLESLintRule<[], true>;
|
62
62
|
'no-duplicate-fields': import("..").GraphQLESLintRule<any[], false>;
|
63
63
|
'no-hashtag-description': import("..").GraphQLESLintRule<any[], false>;
|
64
|
+
'no-one-place-fragments': import("..").GraphQLESLintRule<any[], false>;
|
64
65
|
'no-root-type': import("..").GraphQLESLintRule<{
|
65
66
|
disallow: ("mutation" | "subscription")[];
|
66
67
|
}[], false>;
|