@graphql-eslint/eslint-plugin 3.14.0-alpha-20221221142641-4e1a924 → 3.14.0-alpha-20221222124206-b82954b
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/README.md +309 -0
- package/cjs/cache.js +30 -0
- package/cjs/configs/base.js +7 -0
- package/cjs/configs/index.js +16 -0
- package/cjs/configs/operations-all.js +31 -0
- package/cjs/configs/operations-recommended.js +56 -0
- package/cjs/configs/relay.js +12 -0
- package/cjs/configs/schema-all.js +23 -0
- package/cjs/configs/schema-recommended.js +52 -0
- package/cjs/documents.js +149 -0
- package/cjs/estree-converter/converter.js +62 -0
- package/cjs/estree-converter/index.js +6 -0
- package/cjs/estree-converter/types.js +2 -0
- package/cjs/estree-converter/utils.js +109 -0
- package/cjs/graphql-config.js +55 -0
- package/cjs/index.js +17 -0
- package/cjs/parser.js +61 -0
- package/cjs/processor.js +78 -0
- package/cjs/rules/alphabetize.js +348 -0
- package/cjs/rules/description-style.js +78 -0
- package/cjs/rules/graphql-js-validation.js +499 -0
- package/cjs/rules/index.js +68 -0
- package/cjs/rules/input-name.js +136 -0
- package/cjs/rules/lone-executable-definition.js +88 -0
- package/cjs/rules/match-document-filename.js +235 -0
- package/cjs/rules/naming-convention.js +310 -0
- package/cjs/rules/no-anonymous-operations.js +67 -0
- package/cjs/rules/no-case-insensitive-enum-values-duplicates.js +61 -0
- package/cjs/rules/no-deprecated.js +124 -0
- package/cjs/rules/no-duplicate-fields.js +112 -0
- package/cjs/rules/no-hashtag-description.js +89 -0
- package/cjs/rules/no-root-type.js +86 -0
- package/cjs/rules/no-scalar-result-type-on-mutation.js +66 -0
- package/cjs/rules/no-typename-prefix.js +65 -0
- package/cjs/rules/no-unreachable-types.js +158 -0
- package/cjs/rules/no-unused-fields.js +130 -0
- package/cjs/rules/relay-arguments.js +121 -0
- package/cjs/rules/relay-connection-types.js +107 -0
- package/cjs/rules/relay-edge-types.js +189 -0
- package/cjs/rules/relay-page-info.js +100 -0
- package/cjs/rules/require-deprecation-date.js +123 -0
- package/cjs/rules/require-deprecation-reason.js +56 -0
- package/cjs/rules/require-description.js +193 -0
- package/cjs/rules/require-field-of-type-query-in-mutation-result.js +72 -0
- package/cjs/rules/require-id-when-available.js +199 -0
- package/cjs/rules/selection-set-depth.js +135 -0
- package/cjs/rules/strict-id-in-types.js +162 -0
- package/cjs/rules/unique-fragment-name.js +90 -0
- package/cjs/rules/unique-operation-name.js +65 -0
- package/cjs/schema.js +42 -0
- package/cjs/testkit.js +183 -0
- package/cjs/types.js +2 -0
- package/cjs/utils.js +96 -0
- package/docs/README.md +82 -0
- package/docs/custom-rules.md +184 -0
- package/docs/deprecated-rules.md +24 -0
- package/docs/parser-options.md +95 -0
- package/docs/parser.md +67 -0
- package/docs/rules/alphabetize.md +194 -0
- package/docs/rules/description-style.md +57 -0
- package/docs/rules/executable-definitions.md +20 -0
- package/docs/rules/fields-on-correct-type.md +23 -0
- package/docs/rules/fragments-on-composite-type.md +20 -0
- package/docs/rules/input-name.md +80 -0
- package/docs/rules/known-argument-names.md +23 -0
- package/docs/rules/known-directives.md +48 -0
- package/docs/rules/known-fragment-names.md +72 -0
- package/docs/rules/known-type-names.md +24 -0
- package/docs/rules/lone-anonymous-operation.md +20 -0
- package/docs/rules/lone-executable-definition.md +59 -0
- package/docs/rules/lone-schema-definition.md +19 -0
- package/docs/rules/match-document-filename.md +181 -0
- package/docs/rules/naming-convention.md +320 -0
- package/docs/rules/no-anonymous-operations.md +43 -0
- package/docs/rules/no-case-insensitive-enum-values-duplicates.md +46 -0
- package/docs/rules/no-deprecated.md +88 -0
- package/docs/rules/no-duplicate-fields.md +69 -0
- package/docs/rules/no-fragment-cycles.md +19 -0
- package/docs/rules/no-hashtag-description.md +62 -0
- package/docs/rules/no-root-type.md +55 -0
- package/docs/rules/no-scalar-result-type-on-mutation.md +39 -0
- package/docs/rules/no-typename-prefix.md +42 -0
- package/docs/rules/no-undefined-variables.md +20 -0
- package/docs/rules/no-unreachable-types.md +52 -0
- package/docs/rules/no-unused-fields.md +64 -0
- package/docs/rules/no-unused-fragments.md +20 -0
- package/docs/rules/no-unused-variables.md +20 -0
- package/docs/rules/one-field-subscriptions.md +19 -0
- package/docs/rules/overlapping-fields-can-be-merged.md +20 -0
- package/docs/rules/possible-fragment-spread.md +21 -0
- package/docs/rules/possible-type-extension.md +19 -0
- package/docs/rules/provided-required-arguments.md +21 -0
- package/docs/rules/relay-arguments.md +59 -0
- package/docs/rules/relay-connection-types.md +43 -0
- package/docs/rules/relay-edge-types.md +60 -0
- package/docs/rules/relay-page-info.md +34 -0
- package/docs/rules/require-deprecation-date.md +59 -0
- package/docs/rules/require-deprecation-reason.md +49 -0
- package/docs/rules/require-description.md +147 -0
- package/docs/rules/require-field-of-type-query-in-mutation-result.md +50 -0
- package/docs/rules/require-id-when-available.md +91 -0
- package/docs/rules/scalar-leafs.md +23 -0
- package/docs/rules/selection-set-depth.md +86 -0
- package/docs/rules/strict-id-in-types.md +129 -0
- package/docs/rules/unique-argument-names.md +19 -0
- package/docs/rules/unique-directive-names-per-location.md +21 -0
- package/docs/rules/unique-directive-names.md +19 -0
- package/docs/rules/unique-enum-value-names.md +16 -0
- package/docs/rules/unique-field-definition-names.md +19 -0
- package/docs/rules/unique-fragment-name.md +52 -0
- package/docs/rules/unique-input-field-names.md +19 -0
- package/docs/rules/unique-operation-name.md +56 -0
- package/docs/rules/unique-operation-types.md +19 -0
- package/docs/rules/unique-type-names.md +19 -0
- package/docs/rules/unique-variable-names.md +19 -0
- package/docs/rules/value-literals-of-correct-type.md +22 -0
- package/docs/rules/variables-are-input-types.md +20 -0
- package/docs/rules/variables-in-allowed-position.md +19 -0
- package/package.json +8 -11
- package/{cache.d.ts → typings/cache.d.cts} +0 -0
- package/typings/cache.d.ts +10 -0
- package/typings/configs/base.d.cts +5 -0
- package/typings/configs/base.d.ts +5 -0
- package/typings/configs/index.d.cts +139 -0
- package/typings/configs/index.d.ts +139 -0
- package/typings/configs/operations-all.d.cts +20 -0
- package/typings/configs/operations-all.d.ts +20 -0
- package/typings/configs/operations-recommended.d.cts +50 -0
- package/typings/configs/operations-recommended.d.ts +50 -0
- package/typings/configs/relay.d.cts +10 -0
- package/typings/configs/relay.d.ts +10 -0
- package/typings/configs/schema-all.d.cts +15 -0
- package/typings/configs/schema-all.d.ts +15 -0
- package/typings/configs/schema-recommended.d.cts +47 -0
- package/typings/configs/schema-recommended.d.ts +47 -0
- package/{documents.d.ts → typings/documents.d.cts} +0 -0
- package/typings/documents.d.ts +21 -0
- package/{estree-converter/converter.d.ts → typings/estree-converter/converter.d.cts} +0 -0
- package/typings/estree-converter/converter.d.ts +3 -0
- package/{estree-converter/index.d.ts → typings/estree-converter/index.d.cts} +0 -0
- package/typings/estree-converter/index.d.ts +3 -0
- package/{estree-converter/types.d.ts → typings/estree-converter/types.d.cts} +0 -0
- package/typings/estree-converter/types.d.ts +40 -0
- package/{estree-converter/utils.d.ts → typings/estree-converter/utils.d.cts} +0 -0
- package/typings/estree-converter/utils.d.ts +13 -0
- package/{graphql-config.d.ts → typings/graphql-config.d.cts} +0 -0
- package/typings/graphql-config.d.ts +4 -0
- package/typings/index.d.cts +9 -0
- package/{index.d.ts → typings/index.d.ts} +1 -5
- package/{parser.d.ts → typings/parser.d.cts} +0 -0
- package/typings/parser.d.ts +2 -0
- package/{processor.d.ts → typings/processor.d.cts} +0 -0
- package/typings/processor.d.ts +6 -0
- package/{rules/alphabetize.d.ts → typings/rules/alphabetize.d.cts} +0 -0
- package/typings/rules/alphabetize.d.ts +76 -0
- package/{rules/description-style.d.ts → typings/rules/description-style.d.cts} +0 -0
- package/typings/rules/description-style.d.ts +20 -0
- package/{rules/graphql-js-validation.d.ts → typings/rules/graphql-js-validation.d.cts} +0 -0
- package/typings/rules/graphql-js-validation.d.ts +2 -0
- package/{rules/index.d.ts → typings/rules/index.d.cts} +0 -0
- package/typings/rules/index.d.ts +104 -0
- package/{rules/input-name.d.ts → typings/rules/input-name.d.cts} +0 -0
- package/typings/rules/input-name.d.ts +35 -0
- package/{rules/lone-executable-definition.d.ts → typings/rules/lone-executable-definition.d.cts} +0 -0
- package/typings/rules/lone-executable-definition.d.ts +26 -0
- package/{rules/match-document-filename.d.ts → typings/rules/match-document-filename.d.cts} +0 -0
- package/typings/rules/match-document-filename.d.ts +72 -0
- package/{rules/naming-convention.d.ts → typings/rules/naming-convention.d.cts} +0 -0
- package/typings/rules/naming-convention.d.ts +83 -0
- package/{rules/no-anonymous-operations.d.ts → typings/rules/no-anonymous-operations.d.cts} +0 -0
- package/{rules/no-case-insensitive-enum-values-duplicates.d.ts → typings/rules/no-anonymous-operations.d.ts} +0 -0
- package/{rules/no-hashtag-description.d.ts → typings/rules/no-case-insensitive-enum-values-duplicates.d.cts} +0 -0
- package/{rules/no-scalar-result-type-on-mutation.d.ts → typings/rules/no-case-insensitive-enum-values-duplicates.d.ts} +0 -0
- package/{rules/no-deprecated.d.ts → typings/rules/no-deprecated.d.cts} +0 -0
- package/typings/rules/no-deprecated.d.ts +2 -0
- package/{rules/no-duplicate-fields.d.ts → typings/rules/no-duplicate-fields.d.cts} +0 -0
- package/{rules/relay-page-info.d.ts → typings/rules/no-duplicate-fields.d.ts} +0 -0
- package/{rules/no-typename-prefix.d.ts → typings/rules/no-hashtag-description.d.cts} +0 -0
- package/{rules/no-unreachable-types.d.ts → typings/rules/no-hashtag-description.d.ts} +0 -0
- package/{rules/no-root-type.d.ts → typings/rules/no-root-type.d.cts} +0 -0
- package/typings/rules/no-root-type.d.ts +25 -0
- package/{rules/no-unused-fields.d.ts → typings/rules/no-scalar-result-type-on-mutation.d.cts} +0 -0
- package/{rules/unique-operation-name.d.ts → typings/rules/no-scalar-result-type-on-mutation.d.ts} +0 -0
- package/typings/rules/no-typename-prefix.d.cts +2 -0
- package/typings/rules/no-typename-prefix.d.ts +2 -0
- package/typings/rules/no-unreachable-types.d.cts +2 -0
- package/typings/rules/no-unreachable-types.d.ts +2 -0
- package/typings/rules/no-unused-fields.d.cts +2 -0
- package/typings/rules/no-unused-fields.d.ts +2 -0
- package/{rules/relay-arguments.d.ts → typings/rules/relay-arguments.d.cts} +0 -0
- package/typings/rules/relay-arguments.d.ts +21 -0
- package/{rules/relay-connection-types.d.ts → typings/rules/relay-connection-types.d.cts} +0 -0
- package/typings/rules/relay-connection-types.d.ts +4 -0
- package/{rules/relay-edge-types.d.ts → typings/rules/relay-edge-types.d.cts} +0 -0
- package/typings/rules/relay-edge-types.d.ts +31 -0
- package/{rules/require-deprecation-reason.d.ts → typings/rules/relay-page-info.d.cts} +0 -0
- package/{rules/require-field-of-type-query-in-mutation-result.d.ts → typings/rules/relay-page-info.d.ts} +0 -0
- package/{rules/require-deprecation-date.d.ts → typings/rules/require-deprecation-date.d.cts} +0 -0
- package/typings/rules/require-deprecation-date.d.ts +18 -0
- package/typings/rules/require-deprecation-reason.d.cts +2 -0
- package/typings/rules/require-deprecation-reason.d.ts +2 -0
- package/{rules/require-description.d.ts → typings/rules/require-description.d.cts} +0 -0
- package/typings/rules/require-description.d.ts +14 -0
- package/typings/rules/require-field-of-type-query-in-mutation-result.d.cts +2 -0
- package/typings/rules/require-field-of-type-query-in-mutation-result.d.ts +2 -0
- package/{rules/require-id-when-available.d.ts → typings/rules/require-id-when-available.d.cts} +0 -0
- package/typings/rules/require-id-when-available.d.ts +36 -0
- package/{rules/selection-set-depth.d.ts → typings/rules/selection-set-depth.d.cts} +0 -0
- package/typings/rules/selection-set-depth.d.ts +28 -0
- package/{rules/strict-id-in-types.d.ts → typings/rules/strict-id-in-types.d.cts} +0 -0
- package/typings/rules/strict-id-in-types.d.ts +57 -0
- package/{rules/unique-fragment-name.d.ts → typings/rules/unique-fragment-name.d.cts} +0 -0
- package/typings/rules/unique-fragment-name.d.ts +5 -0
- package/typings/rules/unique-operation-name.d.cts +2 -0
- package/typings/rules/unique-operation-name.d.ts +2 -0
- package/{schema.d.ts → typings/schema.d.cts} +0 -0
- package/typings/schema.d.ts +3 -0
- package/{testkit.d.ts → typings/testkit.d.cts} +0 -0
- package/typings/testkit.d.ts +27 -0
- package/{types.d.ts → typings/types.d.cts} +0 -0
- package/typings/types.d.ts +81 -0
- package/{utils.d.ts → typings/utils.d.cts} +0 -0
- package/typings/utils.d.ts +34 -0
- package/configs/base.json +0 -4
- package/configs/operations-all.json +0 -25
- package/configs/operations-recommended.json +0 -50
- package/configs/relay.json +0 -9
- package/configs/schema-all.json +0 -17
- package/configs/schema-recommended.json +0 -49
- package/index.js +0 -4995
- package/index.mjs +0 -4983
package/cjs/documents.js
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.getDocuments = void 0;
|
4
|
+
const tslib_1 = require("tslib");
|
5
|
+
const path_1 = require("path");
|
6
|
+
const graphql_1 = require("graphql");
|
7
|
+
const debug_1 = tslib_1.__importDefault(require("debug"));
|
8
|
+
const fast_glob_1 = tslib_1.__importDefault(require("fast-glob"));
|
9
|
+
const utils_1 = require("./utils");
|
10
|
+
const cache_1 = require("./cache");
|
11
|
+
const debug = (0, debug_1.default)('graphql-eslint:operations');
|
12
|
+
const handleVirtualPath = (documents) => {
|
13
|
+
const filepathMap = Object.create(null);
|
14
|
+
return documents.map(source => {
|
15
|
+
var _a;
|
16
|
+
const { location } = source;
|
17
|
+
if (['.gql', '.graphql'].some(extension => location.endsWith(extension))) {
|
18
|
+
return source;
|
19
|
+
}
|
20
|
+
(_a = filepathMap[location]) !== null && _a !== void 0 ? _a : (filepathMap[location] = -1);
|
21
|
+
const index = (filepathMap[location] += 1);
|
22
|
+
return {
|
23
|
+
...source,
|
24
|
+
location: (0, path_1.resolve)(location, `${index}_document.graphql`),
|
25
|
+
};
|
26
|
+
});
|
27
|
+
};
|
28
|
+
const operationsCache = new cache_1.ModuleCache();
|
29
|
+
const siblingOperationsCache = new Map();
|
30
|
+
const getSiblings = (project) => {
|
31
|
+
const documentsKey = project.documents;
|
32
|
+
if (!documentsKey) {
|
33
|
+
return [];
|
34
|
+
}
|
35
|
+
let siblings = operationsCache.get(documentsKey);
|
36
|
+
if (!siblings) {
|
37
|
+
debug('Loading operations from %o', project.documents);
|
38
|
+
const documents = project.loadDocumentsSync(project.documents, {
|
39
|
+
skipGraphQLImport: true,
|
40
|
+
pluckConfig: project.extensions.pluckConfig,
|
41
|
+
});
|
42
|
+
if (debug.enabled) {
|
43
|
+
debug('Loaded %d operations', documents.length);
|
44
|
+
const operationsPaths = fast_glob_1.default.sync(project.documents, { absolute: true });
|
45
|
+
debug('Operations pointers %O', operationsPaths);
|
46
|
+
}
|
47
|
+
siblings = handleVirtualPath(documents);
|
48
|
+
operationsCache.set(documentsKey, siblings);
|
49
|
+
}
|
50
|
+
return siblings;
|
51
|
+
};
|
52
|
+
function getDocuments(project) {
|
53
|
+
const siblings = getSiblings(project);
|
54
|
+
if (siblings.length === 0) {
|
55
|
+
let printed = false;
|
56
|
+
const noopWarn = () => {
|
57
|
+
if (!printed) {
|
58
|
+
utils_1.logger.warn('getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!');
|
59
|
+
printed = true;
|
60
|
+
}
|
61
|
+
return [];
|
62
|
+
};
|
63
|
+
return {
|
64
|
+
available: false,
|
65
|
+
getFragment: noopWarn,
|
66
|
+
getFragments: noopWarn,
|
67
|
+
getFragmentByType: noopWarn,
|
68
|
+
getFragmentsInUse: noopWarn,
|
69
|
+
getOperation: noopWarn,
|
70
|
+
getOperations: noopWarn,
|
71
|
+
getOperationByType: noopWarn,
|
72
|
+
};
|
73
|
+
}
|
74
|
+
// Since the siblings array is cached, we can use it as cache key.
|
75
|
+
// We should get the same array reference each time we get
|
76
|
+
// to this point for the same graphql project
|
77
|
+
if (siblingOperationsCache.has(siblings)) {
|
78
|
+
return siblingOperationsCache.get(siblings);
|
79
|
+
}
|
80
|
+
let fragmentsCache = null;
|
81
|
+
const getFragments = () => {
|
82
|
+
if (fragmentsCache === null) {
|
83
|
+
const result = [];
|
84
|
+
for (const source of siblings) {
|
85
|
+
for (const definition of source.document.definitions) {
|
86
|
+
if (definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION) {
|
87
|
+
result.push({
|
88
|
+
filePath: source.location,
|
89
|
+
document: definition,
|
90
|
+
});
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
fragmentsCache = result;
|
95
|
+
}
|
96
|
+
return fragmentsCache;
|
97
|
+
};
|
98
|
+
let cachedOperations = null;
|
99
|
+
const getOperations = () => {
|
100
|
+
if (cachedOperations === null) {
|
101
|
+
const result = [];
|
102
|
+
for (const source of siblings) {
|
103
|
+
for (const definition of source.document.definitions) {
|
104
|
+
if (definition.kind === graphql_1.Kind.OPERATION_DEFINITION) {
|
105
|
+
result.push({
|
106
|
+
filePath: source.location,
|
107
|
+
document: definition,
|
108
|
+
});
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
cachedOperations = result;
|
113
|
+
}
|
114
|
+
return cachedOperations;
|
115
|
+
};
|
116
|
+
const getFragment = (name) => getFragments().filter(f => { var _a; return ((_a = f.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; });
|
117
|
+
const collectFragments = (selectable, recursive, collected = new Map()) => {
|
118
|
+
(0, graphql_1.visit)(selectable, {
|
119
|
+
FragmentSpread(spread) {
|
120
|
+
const fragmentName = spread.name.value;
|
121
|
+
const [fragment] = getFragment(fragmentName);
|
122
|
+
if (!fragment) {
|
123
|
+
utils_1.logger.warn(`Unable to locate fragment named "${fragmentName}", please make sure it's loaded using "parserOptions.operations"`);
|
124
|
+
return;
|
125
|
+
}
|
126
|
+
if (!collected.has(fragmentName)) {
|
127
|
+
collected.set(fragmentName, fragment.document);
|
128
|
+
if (recursive) {
|
129
|
+
collectFragments(fragment.document, recursive, collected);
|
130
|
+
}
|
131
|
+
}
|
132
|
+
},
|
133
|
+
});
|
134
|
+
return collected;
|
135
|
+
};
|
136
|
+
const siblingOperations = {
|
137
|
+
available: true,
|
138
|
+
getFragment,
|
139
|
+
getFragments,
|
140
|
+
getFragmentByType: typeName => getFragments().filter(f => { var _a, _b; return ((_b = (_a = f.document.typeCondition) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.value) === typeName; }),
|
141
|
+
getFragmentsInUse: (selectable, recursive = true) => Array.from(collectFragments(selectable, recursive).values()),
|
142
|
+
getOperation: name => getOperations().filter(o => { var _a; return ((_a = o.document.name) === null || _a === void 0 ? void 0 : _a.value) === name; }),
|
143
|
+
getOperations,
|
144
|
+
getOperationByType: type => getOperations().filter(o => o.document.operation === type),
|
145
|
+
};
|
146
|
+
siblingOperationsCache.set(siblings, siblingOperations);
|
147
|
+
return siblingOperations;
|
148
|
+
}
|
149
|
+
exports.getDocuments = getDocuments;
|
@@ -0,0 +1,62 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.convertToESTree = void 0;
|
4
|
+
const graphql_1 = require("graphql");
|
5
|
+
const utils_1 = require("./utils");
|
6
|
+
function convertToESTree(node, schema) {
|
7
|
+
const typeInfo = schema ? new graphql_1.TypeInfo(schema) : null;
|
8
|
+
const visitor = {
|
9
|
+
leave(node, key, parent) {
|
10
|
+
const leadingComments = 'description' in node && node.description
|
11
|
+
? [
|
12
|
+
{
|
13
|
+
type: node.description.block ? 'Block' : 'Line',
|
14
|
+
value: node.description.value,
|
15
|
+
},
|
16
|
+
]
|
17
|
+
: [];
|
18
|
+
const calculatedTypeInfo = typeInfo
|
19
|
+
? {
|
20
|
+
argument: typeInfo.getArgument(),
|
21
|
+
defaultValue: typeInfo.getDefaultValue(),
|
22
|
+
directive: typeInfo.getDirective(),
|
23
|
+
enumValue: typeInfo.getEnumValue(),
|
24
|
+
fieldDef: typeInfo.getFieldDef(),
|
25
|
+
inputType: typeInfo.getInputType(),
|
26
|
+
parentInputType: typeInfo.getParentInputType(),
|
27
|
+
parentType: typeInfo.getParentType(),
|
28
|
+
gqlType: typeInfo.getType(),
|
29
|
+
}
|
30
|
+
: {};
|
31
|
+
const rawNode = () => {
|
32
|
+
if (parent && key !== undefined) {
|
33
|
+
return parent[key];
|
34
|
+
}
|
35
|
+
return node.kind === graphql_1.Kind.DOCUMENT
|
36
|
+
? {
|
37
|
+
...node,
|
38
|
+
definitions: node.definitions.map(definition => definition.rawNode()),
|
39
|
+
}
|
40
|
+
: node;
|
41
|
+
};
|
42
|
+
const commonFields = {
|
43
|
+
...node,
|
44
|
+
type: node.kind,
|
45
|
+
loc: (0, utils_1.convertLocation)(node.loc),
|
46
|
+
range: [node.loc.start, node.loc.end],
|
47
|
+
leadingComments,
|
48
|
+
// Use function to prevent RangeError: Maximum call stack size exceeded
|
49
|
+
typeInfo: () => calculatedTypeInfo,
|
50
|
+
rawNode,
|
51
|
+
};
|
52
|
+
return 'type' in node
|
53
|
+
? {
|
54
|
+
...commonFields,
|
55
|
+
gqlType: node.type,
|
56
|
+
}
|
57
|
+
: commonFields;
|
58
|
+
},
|
59
|
+
};
|
60
|
+
return (0, graphql_1.visit)(node, typeInfo ? (0, graphql_1.visitWithTypeInfo)(typeInfo, visitor) : visitor);
|
61
|
+
}
|
62
|
+
exports.convertToESTree = convertToESTree;
|
@@ -0,0 +1,6 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const tslib_1 = require("tslib");
|
4
|
+
tslib_1.__exportStar(require("./converter"), exports);
|
5
|
+
tslib_1.__exportStar(require("./types"), exports);
|
6
|
+
tslib_1.__exportStar(require("./utils"), exports);
|
@@ -0,0 +1,109 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.convertLocation = exports.extractComments = exports.extractTokens = exports.convertToken = exports.getBaseType = exports.valueFromNode = void 0;
|
4
|
+
const graphql_1 = require("graphql");
|
5
|
+
const valueFromASTUntyped_1 = require("graphql/utilities/valueFromASTUntyped");
|
6
|
+
const valueFromNode = (...args) => {
|
7
|
+
return (0, valueFromASTUntyped_1.valueFromASTUntyped)(...args);
|
8
|
+
};
|
9
|
+
exports.valueFromNode = valueFromNode;
|
10
|
+
function getBaseType(type) {
|
11
|
+
if ((0, graphql_1.isNonNullType)(type) || (0, graphql_1.isListType)(type)) {
|
12
|
+
return getBaseType(type.ofType);
|
13
|
+
}
|
14
|
+
return type;
|
15
|
+
}
|
16
|
+
exports.getBaseType = getBaseType;
|
17
|
+
function convertToken(token, type) {
|
18
|
+
const { line, column, end, start, value } = token;
|
19
|
+
return {
|
20
|
+
type,
|
21
|
+
value,
|
22
|
+
/*
|
23
|
+
* ESLint has 0-based column number
|
24
|
+
* https://eslint.org/docs/developer-guide/working-with-rules#contextreport
|
25
|
+
*/
|
26
|
+
loc: {
|
27
|
+
start: {
|
28
|
+
line,
|
29
|
+
column: column - 1,
|
30
|
+
},
|
31
|
+
end: {
|
32
|
+
line,
|
33
|
+
column: column - 1 + (end - start),
|
34
|
+
},
|
35
|
+
},
|
36
|
+
range: [start, end],
|
37
|
+
};
|
38
|
+
}
|
39
|
+
exports.convertToken = convertToken;
|
40
|
+
function getLexer(source) {
|
41
|
+
// GraphQL v14
|
42
|
+
const gqlLanguage = require('graphql/language');
|
43
|
+
if (gqlLanguage && gqlLanguage.createLexer) {
|
44
|
+
return gqlLanguage.createLexer(source, {});
|
45
|
+
}
|
46
|
+
// GraphQL v15
|
47
|
+
const { Lexer: LexerCls } = require('graphql');
|
48
|
+
if (LexerCls && typeof LexerCls === 'function') {
|
49
|
+
return new LexerCls(source);
|
50
|
+
}
|
51
|
+
throw new Error('Unsupported GraphQL version! Please make sure to use GraphQL v14 or newer!');
|
52
|
+
}
|
53
|
+
function extractTokens(filePath, code) {
|
54
|
+
const source = new graphql_1.Source(code, filePath);
|
55
|
+
const lexer = getLexer(source);
|
56
|
+
const tokens = [];
|
57
|
+
let token = lexer.advance();
|
58
|
+
while (token && token.kind !== graphql_1.TokenKind.EOF) {
|
59
|
+
const result = convertToken(token, token.kind);
|
60
|
+
tokens.push(result);
|
61
|
+
token = lexer.advance();
|
62
|
+
}
|
63
|
+
return tokens;
|
64
|
+
}
|
65
|
+
exports.extractTokens = extractTokens;
|
66
|
+
function extractComments(loc) {
|
67
|
+
if (!loc) {
|
68
|
+
return [];
|
69
|
+
}
|
70
|
+
const comments = [];
|
71
|
+
let token = loc.startToken;
|
72
|
+
while (token) {
|
73
|
+
if (token.kind === graphql_1.TokenKind.COMMENT) {
|
74
|
+
const comment = convertToken(token,
|
75
|
+
// `eslint-disable` directive works only with `Block` type comment
|
76
|
+
token.value.trimStart().startsWith('eslint') ? 'Block' : 'Line');
|
77
|
+
comments.push(comment);
|
78
|
+
}
|
79
|
+
token = token.next;
|
80
|
+
}
|
81
|
+
return comments;
|
82
|
+
}
|
83
|
+
exports.extractComments = extractComments;
|
84
|
+
function convertLocation(location) {
|
85
|
+
const { startToken, endToken, source, start, end } = location;
|
86
|
+
/*
|
87
|
+
* ESLint has 0-based column number
|
88
|
+
* https://eslint.org/docs/developer-guide/working-with-rules#contextreport
|
89
|
+
*/
|
90
|
+
const loc = {
|
91
|
+
start: {
|
92
|
+
/*
|
93
|
+
* Kind.Document has startToken: { line: 0, column: 0 }, we set line as 1 and column as 0
|
94
|
+
*/
|
95
|
+
line: startToken.line === 0 ? 1 : startToken.line,
|
96
|
+
column: startToken.column === 0 ? 0 : startToken.column - 1,
|
97
|
+
},
|
98
|
+
end: {
|
99
|
+
line: endToken.line,
|
100
|
+
column: endToken.column - 1,
|
101
|
+
},
|
102
|
+
source: source.body,
|
103
|
+
};
|
104
|
+
if (loc.start.column === loc.end.column) {
|
105
|
+
loc.end.column += end - start;
|
106
|
+
}
|
107
|
+
return loc;
|
108
|
+
}
|
109
|
+
exports.convertLocation = convertLocation;
|
@@ -0,0 +1,55 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.loadGraphQLConfig = exports.loadOnDiskGraphQLConfig = void 0;
|
4
|
+
const tslib_1 = require("tslib");
|
5
|
+
const path_1 = require("path");
|
6
|
+
const debug_1 = tslib_1.__importDefault(require("debug"));
|
7
|
+
const graphql_config_1 = require("graphql-config");
|
8
|
+
const code_file_loader_1 = require("@graphql-tools/code-file-loader");
|
9
|
+
const debug = (0, debug_1.default)('graphql-eslint:graphql-config');
|
10
|
+
let graphQLConfig;
|
11
|
+
function loadOnDiskGraphQLConfig(filePath) {
|
12
|
+
return (0, graphql_config_1.loadConfigSync)({
|
13
|
+
// load config relative to the file being linted
|
14
|
+
rootDir: (0, path_1.dirname)(filePath),
|
15
|
+
throwOnEmpty: false,
|
16
|
+
throwOnMissing: false,
|
17
|
+
extensions: [codeFileLoaderExtension],
|
18
|
+
});
|
19
|
+
}
|
20
|
+
exports.loadOnDiskGraphQLConfig = loadOnDiskGraphQLConfig;
|
21
|
+
function loadGraphQLConfig(options) {
|
22
|
+
// We don't want cache config on test environment
|
23
|
+
// Otherwise schema and documents will be same for all tests
|
24
|
+
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
25
|
+
return graphQLConfig;
|
26
|
+
}
|
27
|
+
const onDiskConfig = !options.skipGraphQLConfig && loadOnDiskGraphQLConfig(options.filePath);
|
28
|
+
debug('options.skipGraphQLConfig: %o', options.skipGraphQLConfig);
|
29
|
+
if (onDiskConfig) {
|
30
|
+
debug('Graphql-config path %o', onDiskConfig.filepath);
|
31
|
+
}
|
32
|
+
const configOptions = options.projects
|
33
|
+
? { projects: options.projects }
|
34
|
+
: {
|
35
|
+
schema: (options.schema || ''),
|
36
|
+
documents: options.documents || options.operations,
|
37
|
+
extensions: options.extensions,
|
38
|
+
include: options.include,
|
39
|
+
exclude: options.exclude,
|
40
|
+
};
|
41
|
+
graphQLConfig =
|
42
|
+
onDiskConfig ||
|
43
|
+
new graphql_config_1.GraphQLConfig({
|
44
|
+
config: configOptions,
|
45
|
+
filepath: 'virtual-config',
|
46
|
+
}, [codeFileLoaderExtension]);
|
47
|
+
return graphQLConfig;
|
48
|
+
}
|
49
|
+
exports.loadGraphQLConfig = loadGraphQLConfig;
|
50
|
+
const codeFileLoaderExtension = api => {
|
51
|
+
const { schema, documents } = api.loaders;
|
52
|
+
schema.register(new code_file_loader_1.CodeFileLoader());
|
53
|
+
documents.register(new code_file_loader_1.CodeFileLoader());
|
54
|
+
return { name: 'graphql-eslint-loaders' };
|
55
|
+
};
|
package/cjs/index.js
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.configs = exports.processors = exports.requireSiblingsOperations = exports.requireGraphQLSchemaFromContext = exports.parseForESLint = exports.rules = void 0;
|
4
|
+
const tslib_1 = require("tslib");
|
5
|
+
const processor_1 = require("./processor");
|
6
|
+
var rules_1 = require("./rules");
|
7
|
+
Object.defineProperty(exports, "rules", { enumerable: true, get: function () { return rules_1.rules; } });
|
8
|
+
var parser_1 = require("./parser");
|
9
|
+
Object.defineProperty(exports, "parseForESLint", { enumerable: true, get: function () { return parser_1.parseForESLint; } });
|
10
|
+
tslib_1.__exportStar(require("./testkit"), exports);
|
11
|
+
tslib_1.__exportStar(require("./types"), exports);
|
12
|
+
var utils_1 = require("./utils");
|
13
|
+
Object.defineProperty(exports, "requireGraphQLSchemaFromContext", { enumerable: true, get: function () { return utils_1.requireGraphQLSchemaFromContext; } });
|
14
|
+
Object.defineProperty(exports, "requireSiblingsOperations", { enumerable: true, get: function () { return utils_1.requireSiblingsOperations; } });
|
15
|
+
exports.processors = { graphql: processor_1.processor };
|
16
|
+
var configs_1 = require("./configs");
|
17
|
+
Object.defineProperty(exports, "configs", { enumerable: true, get: function () { return configs_1.configs; } });
|
package/cjs/parser.js
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.parseForESLint = void 0;
|
4
|
+
const tslib_1 = require("tslib");
|
5
|
+
const utils_1 = require("@graphql-tools/utils");
|
6
|
+
const graphql_1 = require("graphql");
|
7
|
+
const debug_1 = tslib_1.__importDefault(require("debug"));
|
8
|
+
const estree_converter_1 = require("./estree-converter");
|
9
|
+
const schema_1 = require("./schema");
|
10
|
+
const documents_1 = require("./documents");
|
11
|
+
const graphql_config_1 = require("./graphql-config");
|
12
|
+
const utils_2 = require("./utils");
|
13
|
+
const debug = (0, debug_1.default)('graphql-eslint:parser');
|
14
|
+
debug('cwd %o', utils_2.CWD);
|
15
|
+
function parseForESLint(code, options) {
|
16
|
+
try {
|
17
|
+
const { filePath } = options;
|
18
|
+
// First parse code from file, in case of syntax error do not try load schema,
|
19
|
+
// documents or even graphql-config instance
|
20
|
+
const { document } = (0, utils_1.parseGraphQLSDL)(filePath, code, {
|
21
|
+
...options.graphQLParserOptions,
|
22
|
+
noLocation: false,
|
23
|
+
});
|
24
|
+
const gqlConfig = (0, graphql_config_1.loadGraphQLConfig)(options);
|
25
|
+
const realFilepath = filePath.replace(utils_2.VIRTUAL_DOCUMENT_REGEX, '');
|
26
|
+
const project = gqlConfig.getProjectForFile(realFilepath);
|
27
|
+
const schema = (0, schema_1.getSchema)(project, options.schemaOptions);
|
28
|
+
const rootTree = (0, estree_converter_1.convertToESTree)(document, schema instanceof graphql_1.GraphQLSchema ? schema : null);
|
29
|
+
return {
|
30
|
+
services: {
|
31
|
+
schema,
|
32
|
+
siblingOperations: (0, documents_1.getDocuments)(project),
|
33
|
+
},
|
34
|
+
ast: {
|
35
|
+
comments: (0, estree_converter_1.extractComments)(document.loc),
|
36
|
+
tokens: (0, estree_converter_1.extractTokens)(filePath, code),
|
37
|
+
loc: rootTree.loc,
|
38
|
+
range: rootTree.range,
|
39
|
+
type: 'Program',
|
40
|
+
sourceType: 'script',
|
41
|
+
body: [rootTree],
|
42
|
+
},
|
43
|
+
};
|
44
|
+
}
|
45
|
+
catch (error) {
|
46
|
+
error.message = `[graphql-eslint] ${error.message}`;
|
47
|
+
// In case of GraphQL parser error, we report it to ESLint as a parser error that matches the requirements
|
48
|
+
// of ESLint. This will make sure to display it correctly in IDEs and lint results.
|
49
|
+
if (error instanceof graphql_1.GraphQLError) {
|
50
|
+
const eslintError = {
|
51
|
+
index: error.positions[0],
|
52
|
+
lineNumber: error.locations[0].line,
|
53
|
+
column: error.locations[0].column - 1,
|
54
|
+
message: error.message,
|
55
|
+
};
|
56
|
+
throw eslintError;
|
57
|
+
}
|
58
|
+
throw error;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
exports.parseForESLint = parseForESLint;
|
package/cjs/processor.js
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.processor = void 0;
|
4
|
+
const graphql_tag_pluck_1 = require("@graphql-tools/graphql-tag-pluck");
|
5
|
+
const utils_1 = require("@graphql-tools/utils");
|
6
|
+
const graphql_config_1 = require("./graphql-config");
|
7
|
+
const blocksMap = new Map();
|
8
|
+
let onDiskConfig;
|
9
|
+
let onDiskConfigLoaded = false;
|
10
|
+
const RELEVANT_KEYWORDS = ['gql', 'graphql', 'GraphQL'];
|
11
|
+
exports.processor = {
|
12
|
+
supportsAutofix: true,
|
13
|
+
preprocess(code, filePath) {
|
14
|
+
if (!onDiskConfigLoaded) {
|
15
|
+
onDiskConfig = (0, graphql_config_1.loadOnDiskGraphQLConfig)(filePath);
|
16
|
+
onDiskConfigLoaded = true;
|
17
|
+
}
|
18
|
+
let keywords = RELEVANT_KEYWORDS;
|
19
|
+
const pluckConfig = onDiskConfig === null || onDiskConfig === void 0 ? void 0 : onDiskConfig.getProjectForFile(filePath).extensions.pluckConfig;
|
20
|
+
if (pluckConfig) {
|
21
|
+
const { modules = [], globalGqlIdentifierName = ['gql', 'graphql'], gqlMagicComment = 'GraphQL', } = pluckConfig;
|
22
|
+
keywords = [
|
23
|
+
...new Set([
|
24
|
+
...modules.map(({ identifier }) => identifier),
|
25
|
+
...(0, utils_1.asArray)(globalGqlIdentifierName),
|
26
|
+
gqlMagicComment,
|
27
|
+
].filter(Boolean)),
|
28
|
+
];
|
29
|
+
}
|
30
|
+
if (keywords.every(keyword => !code.includes(keyword))) {
|
31
|
+
return [code];
|
32
|
+
}
|
33
|
+
try {
|
34
|
+
const sources = (0, graphql_tag_pluck_1.gqlPluckFromCodeStringSync)(filePath, code, {
|
35
|
+
skipIndent: true,
|
36
|
+
...pluckConfig,
|
37
|
+
});
|
38
|
+
const isSvelte = filePath.endsWith('.svelte');
|
39
|
+
const blocks = sources.map(item => ({
|
40
|
+
filename: 'document.graphql',
|
41
|
+
text: item.body,
|
42
|
+
lineOffset: item.locationOffset.line - (isSvelte ? 3 : 1),
|
43
|
+
// @ts-expect-error -- `index` field exist but show ts error
|
44
|
+
offset: item.locationOffset.index + (isSvelte ? -52 : 1),
|
45
|
+
}));
|
46
|
+
blocksMap.set(filePath, blocks);
|
47
|
+
return [...blocks, code /* source code must be provided and be last */];
|
48
|
+
}
|
49
|
+
catch (_a) {
|
50
|
+
// in case of parsing error return code as is
|
51
|
+
return [code];
|
52
|
+
}
|
53
|
+
},
|
54
|
+
postprocess(messages, filePath) {
|
55
|
+
const blocks = blocksMap.get(filePath) || [];
|
56
|
+
for (let i = 0; i < blocks.length; i += 1) {
|
57
|
+
const { lineOffset, offset } = blocks[i];
|
58
|
+
for (const message of messages[i]) {
|
59
|
+
message.line += lineOffset;
|
60
|
+
// endLine can not exist if only `loc: { start, column }` was provided to context.report
|
61
|
+
if (typeof message.endLine === 'number') {
|
62
|
+
message.endLine += lineOffset;
|
63
|
+
}
|
64
|
+
if (message.fix) {
|
65
|
+
message.fix.range[0] += offset;
|
66
|
+
message.fix.range[1] += offset;
|
67
|
+
}
|
68
|
+
for (const suggestion of message.suggestions || []) {
|
69
|
+
suggestion.fix.range[0] += offset;
|
70
|
+
suggestion.fix.range[1] += offset;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
const result = messages.flat();
|
75
|
+
// sort eslint/graphql-eslint messages by line/column
|
76
|
+
return result.sort((a, b) => a.line - b.line || a.column - b.column);
|
77
|
+
},
|
78
|
+
};
|