@graphql-eslint/eslint-plugin 3.12.0-alpha-20220929103858-c00a837 → 3.12.0-alpha-20221008232037-33da317
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/graphql-config.d.ts +1 -1
- package/index.js +48 -63
- package/index.mjs +50 -65
- package/package.json +7 -7
- package/parser.d.ts +1 -1
- package/rules/match-document-filename.d.ts +0 -1
- package/schema.d.ts +1 -1
- package/testkit.d.ts +2 -2
- package/types.d.ts +1 -1
package/graphql-config.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
import { GraphQLConfig } from 'graphql-config';
|
2
2
|
import { ParserOptions } from './types';
|
3
3
|
export declare function loadOnDiskGraphQLConfig(filePath: string): GraphQLConfig;
|
4
|
-
export declare function loadGraphQLConfig(options
|
4
|
+
export declare function loadGraphQLConfig(options: ParserOptions): GraphQLConfig;
|
package/index.js
CHANGED
@@ -24,15 +24,24 @@ const codeFrame = require('@babel/code-frame');
|
|
24
24
|
const debug = debugFactory('graphql-eslint:graphql-config');
|
25
25
|
let graphQLConfig;
|
26
26
|
function loadOnDiskGraphQLConfig(filePath) {
|
27
|
-
|
27
|
+
const rootDir = path.dirname(filePath);
|
28
|
+
const config = graphqlConfig.loadConfigSync({
|
28
29
|
// load config relative to the file being linted
|
29
|
-
rootDir
|
30
|
+
rootDir,
|
30
31
|
throwOnEmpty: false,
|
31
32
|
throwOnMissing: false,
|
32
|
-
|
33
|
+
});
|
34
|
+
if (!config) {
|
35
|
+
return null;
|
36
|
+
}
|
37
|
+
const project = config.getProjectForFile(filePath);
|
38
|
+
return graphqlConfig.loadConfigSync({
|
39
|
+
rootDir,
|
40
|
+
extensions: [codeFileLoaderExtension(project.extensions.pluckConfig)],
|
33
41
|
});
|
34
42
|
}
|
35
|
-
function loadGraphQLConfig(options
|
43
|
+
function loadGraphQLConfig(options) {
|
44
|
+
var _a;
|
36
45
|
// We don't want cache config on test environment
|
37
46
|
// Otherwise schema and documents will be same for all tests
|
38
47
|
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
@@ -57,53 +66,56 @@ function loadGraphQLConfig(options = {}) {
|
|
57
66
|
new graphqlConfig.GraphQLConfig({
|
58
67
|
config: configOptions,
|
59
68
|
filepath: 'virtual-config',
|
60
|
-
}, [
|
69
|
+
}, [codeFileLoaderExtension((_a = options.extensions) === null || _a === void 0 ? void 0 : _a.pluckConfig)]);
|
61
70
|
return graphQLConfig;
|
62
71
|
}
|
63
|
-
const
|
64
|
-
api.loaders
|
65
|
-
|
72
|
+
const codeFileLoaderExtension = (pluckConfig) => api => {
|
73
|
+
const { schema, documents } = api.loaders;
|
74
|
+
schema.register(new codeFileLoader.CodeFileLoader({ pluckConfig }));
|
75
|
+
documents.register(new codeFileLoader.CodeFileLoader({ pluckConfig }));
|
66
76
|
return { name: 'graphql-eslint-loaders' };
|
67
77
|
};
|
68
78
|
|
69
79
|
const blocksMap = new Map();
|
70
80
|
let onDiskConfig;
|
81
|
+
let pluckConfig;
|
82
|
+
let RELEVANT_KEYWORDS;
|
71
83
|
const processor = {
|
72
84
|
supportsAutofix: true,
|
73
85
|
preprocess(code, filePath) {
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
...utils.asArray(globalGqlIdentifierName),
|
86
|
+
if (!pluckConfig) {
|
87
|
+
onDiskConfig = loadOnDiskGraphQLConfig(filePath);
|
88
|
+
const { modules = [], globalGqlIdentifierName = ['gql', 'graphql'], gqlMagicComment = 'GraphQL', } = (onDiskConfig === null || onDiskConfig === void 0 ? void 0 : onDiskConfig.getProjectForFile(filePath).extensions.pluckConfig) || {};
|
89
|
+
pluckConfig = {
|
90
|
+
skipIndent: true,
|
91
|
+
modules,
|
92
|
+
globalGqlIdentifierName,
|
82
93
|
gqlMagicComment,
|
83
|
-
|
84
|
-
|
94
|
+
};
|
95
|
+
RELEVANT_KEYWORDS = [
|
96
|
+
...new Set([
|
97
|
+
...modules.map(({ identifier }) => identifier),
|
98
|
+
...utils.asArray(globalGqlIdentifierName),
|
99
|
+
gqlMagicComment,
|
100
|
+
].filter(Boolean)),
|
101
|
+
];
|
102
|
+
}
|
85
103
|
if (RELEVANT_KEYWORDS.every(keyword => !code.includes(keyword))) {
|
86
104
|
return [code];
|
87
105
|
}
|
88
106
|
try {
|
89
|
-
const
|
90
|
-
|
91
|
-
filePath,
|
92
|
-
options: {
|
93
|
-
skipIndent: true,
|
94
|
-
...graphQLTagPluckOptions,
|
95
|
-
},
|
96
|
-
});
|
97
|
-
const blocks = extractedDocuments.map(item => ({
|
107
|
+
const sources = graphqlTagPluck.gqlPluckFromCodeStringSync(filePath, code, pluckConfig);
|
108
|
+
const blocks = sources.map(item => ({
|
98
109
|
filename: 'document.graphql',
|
99
|
-
text: item.
|
100
|
-
lineOffset: item.
|
101
|
-
|
110
|
+
text: item.body,
|
111
|
+
lineOffset: item.locationOffset.line - 1,
|
112
|
+
// @ts-expect-error -- `index` field exist but show ts error
|
113
|
+
offset: item.locationOffset.index + 1,
|
102
114
|
}));
|
103
115
|
blocksMap.set(filePath, blocks);
|
104
116
|
return [...blocks, code /* source code must be provided and be last */];
|
105
117
|
}
|
106
|
-
catch (
|
118
|
+
catch (_a) {
|
107
119
|
// in case of parsing error return code as is
|
108
120
|
return [code];
|
109
121
|
}
|
@@ -1212,32 +1224,6 @@ const rule$3 = {
|
|
1212
1224
|
fullName
|
1213
1225
|
}
|
1214
1226
|
}
|
1215
|
-
`,
|
1216
|
-
},
|
1217
|
-
{
|
1218
|
-
title: 'Correct',
|
1219
|
-
usage: [{ fragment: { style: 'kebab-case', suffix: 'Mutation', prefix: 'mutation.' } }],
|
1220
|
-
name: 'mutation.add-alert.graphql',
|
1221
|
-
code: /* GraphQL */ `
|
1222
|
-
# mutation.add-alert.graphql
|
1223
|
-
mutation addAlert($input: AddAlertInput!) {
|
1224
|
-
addAlert(input: $input) {
|
1225
|
-
...AlertFields
|
1226
|
-
}
|
1227
|
-
}
|
1228
|
-
`,
|
1229
|
-
},
|
1230
|
-
{
|
1231
|
-
title: 'Correct',
|
1232
|
-
usage: [{ fragment: { prefix: 'query.' } }],
|
1233
|
-
name: 'query.me.graphql',
|
1234
|
-
code: /* GraphQL */ `
|
1235
|
-
# query.me.graphql
|
1236
|
-
query me {
|
1237
|
-
me {
|
1238
|
-
...UserFields
|
1239
|
-
}
|
1240
|
-
}
|
1241
1227
|
`,
|
1242
1228
|
},
|
1243
1229
|
],
|
@@ -1267,7 +1253,6 @@ const rule$3 = {
|
|
1267
1253
|
properties: {
|
1268
1254
|
style: { enum: CASE_STYLES },
|
1269
1255
|
suffix: { type: 'string' },
|
1270
|
-
prefix: { type: 'string' },
|
1271
1256
|
},
|
1272
1257
|
},
|
1273
1258
|
},
|
@@ -1333,13 +1318,13 @@ const rule$3 = {
|
|
1333
1318
|
option = { style: option };
|
1334
1319
|
}
|
1335
1320
|
const expectedExtension = options.fileExtension || fileExtension;
|
1336
|
-
let expectedFilename
|
1321
|
+
let expectedFilename;
|
1337
1322
|
if (option.style) {
|
1338
1323
|
expectedFilename =
|
1339
1324
|
option.style === 'matchDocumentStyle' ? docName : convertCase(option.style, docName);
|
1340
1325
|
}
|
1341
1326
|
else {
|
1342
|
-
expectedFilename
|
1327
|
+
expectedFilename = filename;
|
1343
1328
|
}
|
1344
1329
|
expectedFilename += (option.suffix || '') + expectedExtension;
|
1345
1330
|
const filenameWithExtension = filename + expectedExtension;
|
@@ -4468,10 +4453,10 @@ function getSiblingOperations(projectForFile) {
|
|
4468
4453
|
|
4469
4454
|
const debug$3 = debugFactory('graphql-eslint:parser');
|
4470
4455
|
debug$3('cwd %o', process.cwd());
|
4471
|
-
function parseForESLint(code, options
|
4456
|
+
function parseForESLint(code, options) {
|
4472
4457
|
try {
|
4473
|
-
const filePath = options
|
4474
|
-
const realFilepath =
|
4458
|
+
const { filePath } = options;
|
4459
|
+
const realFilepath = getOnDiskFilepath(filePath);
|
4475
4460
|
const gqlConfig = loadGraphQLConfig(options);
|
4476
4461
|
const projectForFile = realFilepath
|
4477
4462
|
? gqlConfig.getProjectForFile(realFilepath)
|
package/index.mjs
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
import {
|
1
|
+
import { gqlPluckFromCodeStringSync } from '@graphql-tools/graphql-tag-pluck';
|
2
2
|
import { asArray, getDocumentNodeFromSchema, parseGraphQLSDL } from '@graphql-tools/utils';
|
3
3
|
import { dirname, extname, basename, relative, resolve } from 'path';
|
4
4
|
import debugFactory from 'debug';
|
5
|
-
import {
|
5
|
+
import { GraphQLConfig, loadConfigSync } from 'graphql-config';
|
6
6
|
import { CodeFileLoader } from '@graphql-tools/code-file-loader';
|
7
7
|
import { Kind, visit, validate, TokenKind, isScalarType, DirectiveLocation, isInterfaceType, TypeInfo, visitWithTypeInfo, isObjectType as isObjectType$1, Source, isNonNullType, isListType, GraphQLObjectType, GraphQLInterfaceType, GraphQLSchema, GraphQLError } from 'graphql';
|
8
8
|
import { validateSDL } from 'graphql/validation/validate';
|
@@ -18,15 +18,24 @@ import { codeFrameColumns } from '@babel/code-frame';
|
|
18
18
|
const debug = debugFactory('graphql-eslint:graphql-config');
|
19
19
|
let graphQLConfig;
|
20
20
|
function loadOnDiskGraphQLConfig(filePath) {
|
21
|
-
|
21
|
+
const rootDir = dirname(filePath);
|
22
|
+
const config = loadConfigSync({
|
22
23
|
// load config relative to the file being linted
|
23
|
-
rootDir
|
24
|
+
rootDir,
|
24
25
|
throwOnEmpty: false,
|
25
26
|
throwOnMissing: false,
|
26
|
-
|
27
|
+
});
|
28
|
+
if (!config) {
|
29
|
+
return null;
|
30
|
+
}
|
31
|
+
const project = config.getProjectForFile(filePath);
|
32
|
+
return loadConfigSync({
|
33
|
+
rootDir,
|
34
|
+
extensions: [codeFileLoaderExtension(project.extensions.pluckConfig)],
|
27
35
|
});
|
28
36
|
}
|
29
|
-
function loadGraphQLConfig(options
|
37
|
+
function loadGraphQLConfig(options) {
|
38
|
+
var _a;
|
30
39
|
// We don't want cache config on test environment
|
31
40
|
// Otherwise schema and documents will be same for all tests
|
32
41
|
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
@@ -51,53 +60,56 @@ function loadGraphQLConfig(options = {}) {
|
|
51
60
|
new GraphQLConfig({
|
52
61
|
config: configOptions,
|
53
62
|
filepath: 'virtual-config',
|
54
|
-
}, [
|
63
|
+
}, [codeFileLoaderExtension((_a = options.extensions) === null || _a === void 0 ? void 0 : _a.pluckConfig)]);
|
55
64
|
return graphQLConfig;
|
56
65
|
}
|
57
|
-
const
|
58
|
-
api.loaders
|
59
|
-
|
66
|
+
const codeFileLoaderExtension = (pluckConfig) => api => {
|
67
|
+
const { schema, documents } = api.loaders;
|
68
|
+
schema.register(new CodeFileLoader({ pluckConfig }));
|
69
|
+
documents.register(new CodeFileLoader({ pluckConfig }));
|
60
70
|
return { name: 'graphql-eslint-loaders' };
|
61
71
|
};
|
62
72
|
|
63
73
|
const blocksMap = new Map();
|
64
74
|
let onDiskConfig;
|
75
|
+
let pluckConfig;
|
76
|
+
let RELEVANT_KEYWORDS;
|
65
77
|
const processor = {
|
66
78
|
supportsAutofix: true,
|
67
79
|
preprocess(code, filePath) {
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
...asArray(globalGqlIdentifierName),
|
80
|
+
if (!pluckConfig) {
|
81
|
+
onDiskConfig = loadOnDiskGraphQLConfig(filePath);
|
82
|
+
const { modules = [], globalGqlIdentifierName = ['gql', 'graphql'], gqlMagicComment = 'GraphQL', } = (onDiskConfig === null || onDiskConfig === void 0 ? void 0 : onDiskConfig.getProjectForFile(filePath).extensions.pluckConfig) || {};
|
83
|
+
pluckConfig = {
|
84
|
+
skipIndent: true,
|
85
|
+
modules,
|
86
|
+
globalGqlIdentifierName,
|
76
87
|
gqlMagicComment,
|
77
|
-
|
78
|
-
|
88
|
+
};
|
89
|
+
RELEVANT_KEYWORDS = [
|
90
|
+
...new Set([
|
91
|
+
...modules.map(({ identifier }) => identifier),
|
92
|
+
...asArray(globalGqlIdentifierName),
|
93
|
+
gqlMagicComment,
|
94
|
+
].filter(Boolean)),
|
95
|
+
];
|
96
|
+
}
|
79
97
|
if (RELEVANT_KEYWORDS.every(keyword => !code.includes(keyword))) {
|
80
98
|
return [code];
|
81
99
|
}
|
82
100
|
try {
|
83
|
-
const
|
84
|
-
|
85
|
-
filePath,
|
86
|
-
options: {
|
87
|
-
skipIndent: true,
|
88
|
-
...graphQLTagPluckOptions,
|
89
|
-
},
|
90
|
-
});
|
91
|
-
const blocks = extractedDocuments.map(item => ({
|
101
|
+
const sources = gqlPluckFromCodeStringSync(filePath, code, pluckConfig);
|
102
|
+
const blocks = sources.map(item => ({
|
92
103
|
filename: 'document.graphql',
|
93
|
-
text: item.
|
94
|
-
lineOffset: item.
|
95
|
-
|
104
|
+
text: item.body,
|
105
|
+
lineOffset: item.locationOffset.line - 1,
|
106
|
+
// @ts-expect-error -- `index` field exist but show ts error
|
107
|
+
offset: item.locationOffset.index + 1,
|
96
108
|
}));
|
97
109
|
blocksMap.set(filePath, blocks);
|
98
110
|
return [...blocks, code /* source code must be provided and be last */];
|
99
111
|
}
|
100
|
-
catch (
|
112
|
+
catch (_a) {
|
101
113
|
// in case of parsing error return code as is
|
102
114
|
return [code];
|
103
115
|
}
|
@@ -1206,32 +1218,6 @@ const rule$3 = {
|
|
1206
1218
|
fullName
|
1207
1219
|
}
|
1208
1220
|
}
|
1209
|
-
`,
|
1210
|
-
},
|
1211
|
-
{
|
1212
|
-
title: 'Correct',
|
1213
|
-
usage: [{ fragment: { style: 'kebab-case', suffix: 'Mutation', prefix: 'mutation.' } }],
|
1214
|
-
name: 'mutation.add-alert.graphql',
|
1215
|
-
code: /* GraphQL */ `
|
1216
|
-
# mutation.add-alert.graphql
|
1217
|
-
mutation addAlert($input: AddAlertInput!) {
|
1218
|
-
addAlert(input: $input) {
|
1219
|
-
...AlertFields
|
1220
|
-
}
|
1221
|
-
}
|
1222
|
-
`,
|
1223
|
-
},
|
1224
|
-
{
|
1225
|
-
title: 'Correct',
|
1226
|
-
usage: [{ fragment: { prefix: 'query.' } }],
|
1227
|
-
name: 'query.me.graphql',
|
1228
|
-
code: /* GraphQL */ `
|
1229
|
-
# query.me.graphql
|
1230
|
-
query me {
|
1231
|
-
me {
|
1232
|
-
...UserFields
|
1233
|
-
}
|
1234
|
-
}
|
1235
1221
|
`,
|
1236
1222
|
},
|
1237
1223
|
],
|
@@ -1261,7 +1247,6 @@ const rule$3 = {
|
|
1261
1247
|
properties: {
|
1262
1248
|
style: { enum: CASE_STYLES },
|
1263
1249
|
suffix: { type: 'string' },
|
1264
|
-
prefix: { type: 'string' },
|
1265
1250
|
},
|
1266
1251
|
},
|
1267
1252
|
},
|
@@ -1327,13 +1312,13 @@ const rule$3 = {
|
|
1327
1312
|
option = { style: option };
|
1328
1313
|
}
|
1329
1314
|
const expectedExtension = options.fileExtension || fileExtension;
|
1330
|
-
let expectedFilename
|
1315
|
+
let expectedFilename;
|
1331
1316
|
if (option.style) {
|
1332
1317
|
expectedFilename =
|
1333
1318
|
option.style === 'matchDocumentStyle' ? docName : convertCase(option.style, docName);
|
1334
1319
|
}
|
1335
1320
|
else {
|
1336
|
-
expectedFilename
|
1321
|
+
expectedFilename = filename;
|
1337
1322
|
}
|
1338
1323
|
expectedFilename += (option.suffix || '') + expectedExtension;
|
1339
1324
|
const filenameWithExtension = filename + expectedExtension;
|
@@ -4462,10 +4447,10 @@ function getSiblingOperations(projectForFile) {
|
|
4462
4447
|
|
4463
4448
|
const debug$3 = debugFactory('graphql-eslint:parser');
|
4464
4449
|
debug$3('cwd %o', process.cwd());
|
4465
|
-
function parseForESLint(code, options
|
4450
|
+
function parseForESLint(code, options) {
|
4466
4451
|
try {
|
4467
|
-
const filePath = options
|
4468
|
-
const realFilepath =
|
4452
|
+
const { filePath } = options;
|
4453
|
+
const realFilepath = getOnDiskFilepath(filePath);
|
4469
4454
|
const gqlConfig = loadGraphQLConfig(options);
|
4470
4455
|
const projectForFile = realFilepath
|
4471
4456
|
? gqlConfig.getProjectForFile(realFilepath)
|
package/package.json
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
{
|
2
2
|
"name": "@graphql-eslint/eslint-plugin",
|
3
|
-
"version": "3.12.0-alpha-
|
3
|
+
"version": "3.12.0-alpha-20221008232037-33da317",
|
4
4
|
"description": "GraphQL plugin for ESLint",
|
5
5
|
"sideEffects": false,
|
6
6
|
"peerDependencies": {
|
7
7
|
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
8
8
|
},
|
9
9
|
"dependencies": {
|
10
|
-
"@babel/code-frame": "^7.
|
11
|
-
"@graphql-tools/code-file-loader": "^7.
|
12
|
-
"@graphql-tools/graphql-tag-pluck": "^7.
|
13
|
-
"@graphql-tools/utils": "^8.
|
10
|
+
"@babel/code-frame": "^7.18.6",
|
11
|
+
"@graphql-tools/code-file-loader": "^7.3.6",
|
12
|
+
"@graphql-tools/graphql-tag-pluck": "^7.3.6",
|
13
|
+
"@graphql-tools/utils": "^8.12.0",
|
14
14
|
"chalk": "^4.1.2",
|
15
15
|
"debug": "^4.3.4",
|
16
|
-
"fast-glob": "^3.2.
|
17
|
-
"graphql-config": "^4.3.
|
16
|
+
"fast-glob": "^3.2.12",
|
17
|
+
"graphql-config": "^4.3.5",
|
18
18
|
"graphql-depth-limit": "^1.1.0",
|
19
19
|
"lodash.lowercase": "^4.3.0"
|
20
20
|
},
|
package/parser.d.ts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
import { GraphQLESLintParseResult, ParserOptions } from './types';
|
2
|
-
export declare function parseForESLint(code: string, options
|
2
|
+
export declare function parseForESLint(code: string, options: ParserOptions): GraphQLESLintParseResult;
|
package/schema.d.ts
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
import { GraphQLProjectConfig } from 'graphql-config';
|
2
2
|
import type { ParserOptions, Schema } from './types';
|
3
|
-
export declare function getSchema(projectForFile: GraphQLProjectConfig, options?: ParserOptions): Schema;
|
3
|
+
export declare function getSchema(projectForFile: GraphQLProjectConfig, options?: Omit<ParserOptions, 'filePath'>): Schema;
|
package/testkit.d.ts
CHANGED
@@ -16,9 +16,9 @@ export declare type GraphQLInvalidTestCase<T> = GraphQLValidTestCase<T> & {
|
|
16
16
|
export declare class GraphQLRuleTester extends RuleTester {
|
17
17
|
config: {
|
18
18
|
parser: string;
|
19
|
-
parserOptions: ParserOptions
|
19
|
+
parserOptions: Omit<ParserOptions, 'filePath'>;
|
20
20
|
};
|
21
|
-
constructor(parserOptions?: ParserOptions);
|
21
|
+
constructor(parserOptions?: Omit<ParserOptions, 'filePath'>);
|
22
22
|
fromMockFile(path: string): string;
|
23
23
|
runGraphQLTests<Options, WithTypeInfo extends boolean = false>(ruleId: string, rule: GraphQLESLintRule<Options, WithTypeInfo>, tests: {
|
24
24
|
valid: (string | GraphQLValidTestCase<Options>)[];
|
package/types.d.ts
CHANGED