@graphql-eslint/eslint-plugin 3.3.0-alpha-b07557f.0 → 3.3.0-alpha-d23e9e2.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/docs/rules/possible-type-extension.md +1 -1
- package/graphql-config.d.ts +0 -1
- package/index.js +46 -80
- package/index.mjs +46 -80
- package/package.json +1 -1
- package/utils.d.ts +0 -1
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
- Category: `Schema`
|
4
4
|
- Rule name: `@graphql-eslint/possible-type-extension`
|
5
|
-
- Requires GraphQL Schema: `
|
5
|
+
- Requires GraphQL Schema: `true` [ℹ️](../../README.md#extended-linting-rules-with-graphql-schema)
|
6
6
|
- Requires GraphQL Operations: `false` [ℹ️](../../README.md#extended-linting-rules-with-siblings-operations)
|
7
7
|
|
8
8
|
A type extension is only valid if the type is defined and has the same kind.
|
package/graphql-config.d.ts
CHANGED
package/index.js
CHANGED
@@ -10,10 +10,10 @@ const fs = require('fs');
|
|
10
10
|
const path = require('path');
|
11
11
|
const utils = require('@graphql-tools/utils');
|
12
12
|
const lowerCase = _interopDefault(require('lodash.lowercase'));
|
13
|
-
const graphqlConfig = require('graphql-config');
|
14
|
-
const codeFileLoader = require('@graphql-tools/code-file-loader');
|
15
13
|
const depthLimit = _interopDefault(require('graphql-depth-limit'));
|
16
14
|
const graphqlTagPluck = require('@graphql-tools/graphql-tag-pluck');
|
15
|
+
const graphqlConfig = require('graphql-config');
|
16
|
+
const codeFileLoader = require('@graphql-tools/code-file-loader');
|
17
17
|
const eslint = require('eslint');
|
18
18
|
const codeFrame = require('@babel/code-frame');
|
19
19
|
|
@@ -174,47 +174,6 @@ const configs = {
|
|
174
174
|
'operations-all': operationsAllConfig,
|
175
175
|
};
|
176
176
|
|
177
|
-
let graphQLConfig;
|
178
|
-
function loadCachedGraphQLConfig(options) {
|
179
|
-
// We don't want cache config on test environment
|
180
|
-
// Otherwise schema and documents will be same for all tests
|
181
|
-
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
182
|
-
return graphQLConfig;
|
183
|
-
}
|
184
|
-
graphQLConfig = loadGraphQLConfig(options);
|
185
|
-
return graphQLConfig;
|
186
|
-
}
|
187
|
-
function loadGraphQLConfig(options) {
|
188
|
-
const onDiskConfig = options.skipGraphQLConfig
|
189
|
-
? null
|
190
|
-
: graphqlConfig.loadConfigSync({
|
191
|
-
throwOnEmpty: false,
|
192
|
-
throwOnMissing: false,
|
193
|
-
extensions: [addCodeFileLoaderExtension],
|
194
|
-
});
|
195
|
-
const configOptions = options.projects
|
196
|
-
? { projects: options.projects }
|
197
|
-
: {
|
198
|
-
schema: (options.schema || ''),
|
199
|
-
documents: options.documents || options.operations,
|
200
|
-
extensions: options.extensions,
|
201
|
-
include: options.include,
|
202
|
-
exclude: options.exclude,
|
203
|
-
};
|
204
|
-
graphQLConfig =
|
205
|
-
onDiskConfig ||
|
206
|
-
new graphqlConfig.GraphQLConfig({
|
207
|
-
config: configOptions,
|
208
|
-
filepath: 'virtual-config',
|
209
|
-
}, [addCodeFileLoaderExtension]);
|
210
|
-
return graphQLConfig;
|
211
|
-
}
|
212
|
-
const addCodeFileLoaderExtension = api => {
|
213
|
-
api.loaders.schema.register(new codeFileLoader.CodeFileLoader());
|
214
|
-
api.loaders.documents.register(new codeFileLoader.CodeFileLoader());
|
215
|
-
return { name: 'graphql-eslint-loaders' };
|
216
|
-
};
|
217
|
-
|
218
177
|
function requireSiblingsOperations(ruleName, context) {
|
219
178
|
if (!context.parserServices) {
|
220
179
|
throw new Error(`Rule '${ruleName}' requires 'parserOptions.operations' to be set and loaded. See http://bit.ly/graphql-eslint-operations for more info`);
|
@@ -233,32 +192,6 @@ function requireGraphQLSchemaFromContext(ruleName, context) {
|
|
233
192
|
}
|
234
193
|
return context.parserServices.schema;
|
235
194
|
}
|
236
|
-
const schemaToExtendCache = new Map();
|
237
|
-
function getGraphQLSchemaToExtend(context) {
|
238
|
-
// If parserOptions.schema not set or not loaded, there is no reason to make partial schema aka schemaToExtend
|
239
|
-
if (!context.parserServices.hasTypeInfo) {
|
240
|
-
return null;
|
241
|
-
}
|
242
|
-
const filename = context.getPhysicalFilename();
|
243
|
-
if (!schemaToExtendCache.has(filename)) {
|
244
|
-
const { schema, schemaOptions } = context.parserOptions;
|
245
|
-
const gqlConfig = loadGraphQLConfig({ schema });
|
246
|
-
const projectForFile = gqlConfig.getProjectForFile(filename);
|
247
|
-
let schemaToExtend;
|
248
|
-
try {
|
249
|
-
schemaToExtend = projectForFile.loadSchemaSync(projectForFile.schema, 'GraphQLSchema', {
|
250
|
-
...schemaOptions,
|
251
|
-
ignore: filename,
|
252
|
-
});
|
253
|
-
}
|
254
|
-
catch (_a) {
|
255
|
-
// If error throws just ignore it because maybe schema is located in 1 file
|
256
|
-
schemaToExtend = null;
|
257
|
-
}
|
258
|
-
schemaToExtendCache.set(filename, schemaToExtend);
|
259
|
-
}
|
260
|
-
return schemaToExtendCache.get(filename);
|
261
|
-
}
|
262
195
|
function requireReachableTypesFromContext(ruleName, context) {
|
263
196
|
const schema = requireGraphQLSchemaFromContext(ruleName, context);
|
264
197
|
return context.parserServices.reachableTypes(schema);
|
@@ -393,7 +326,7 @@ function getLocation(loc, fieldName = '', offset) {
|
|
393
326
|
};
|
394
327
|
}
|
395
328
|
|
396
|
-
function validateDocument(
|
329
|
+
function validateDocument(context, schema = null, documentNode, rule, isSchemaToExtend = false) {
|
397
330
|
if (documentNode.definitions.length === 0) {
|
398
331
|
return;
|
399
332
|
}
|
@@ -425,7 +358,8 @@ function validateDocument(sourceNode, context, schema = null, documentNode, rule
|
|
425
358
|
}
|
426
359
|
catch (e) {
|
427
360
|
context.report({
|
428
|
-
|
361
|
+
// Report on first character
|
362
|
+
loc: { column: 0, line: 1 },
|
429
363
|
message: e.message,
|
430
364
|
});
|
431
365
|
}
|
@@ -512,19 +446,13 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode) => {
|
|
512
446
|
console.warn(`You rule "${ruleId}" depends on a GraphQL validation rule "${ruleName}" but it's not available in the "graphql-js" version you are using. Skipping...`);
|
513
447
|
return {};
|
514
448
|
}
|
515
|
-
|
516
|
-
if (docs.requiresSchemaToExtend) {
|
517
|
-
schema = getGraphQLSchemaToExtend(context);
|
518
|
-
}
|
519
|
-
if (docs.requiresSchema) {
|
520
|
-
schema = requireGraphQLSchemaFromContext(ruleId, context);
|
521
|
-
}
|
449
|
+
const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
|
522
450
|
return {
|
523
451
|
Document(node) {
|
524
452
|
const documentNode = getDocumentNode
|
525
453
|
? getDocumentNode({ ruleId, context, schema, node: node.rawNode() })
|
526
454
|
: node.rawNode();
|
527
|
-
validateDocument(
|
455
|
+
validateDocument(context, schema, documentNode, ruleFn, docs.requiresSchemaToExtend);
|
528
456
|
},
|
529
457
|
};
|
530
458
|
},
|
@@ -675,6 +603,7 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
675
603
|
category: 'Schema',
|
676
604
|
description: `A type extension is only valid if the type is defined and has the same kind.`,
|
677
605
|
recommended: false,
|
606
|
+
requiresSchema: true,
|
678
607
|
requiresSchemaToExtend: true,
|
679
608
|
}), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
|
680
609
|
category: ['Schema', 'Operations'],
|
@@ -3775,6 +3704,43 @@ function getSiblingOperations(options, gqlConfig) {
|
|
3775
3704
|
return siblingOperations;
|
3776
3705
|
}
|
3777
3706
|
|
3707
|
+
let graphQLConfig;
|
3708
|
+
function loadGraphQLConfig(options) {
|
3709
|
+
// We don't want cache config on test environment
|
3710
|
+
// Otherwise schema and documents will be same for all tests
|
3711
|
+
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
3712
|
+
return graphQLConfig;
|
3713
|
+
}
|
3714
|
+
const onDiskConfig = options.skipGraphQLConfig
|
3715
|
+
? null
|
3716
|
+
: graphqlConfig.loadConfigSync({
|
3717
|
+
throwOnEmpty: false,
|
3718
|
+
throwOnMissing: false,
|
3719
|
+
extensions: [addCodeFileLoaderExtension],
|
3720
|
+
});
|
3721
|
+
const configOptions = options.projects
|
3722
|
+
? { projects: options.projects }
|
3723
|
+
: {
|
3724
|
+
schema: (options.schema || ''),
|
3725
|
+
documents: options.documents || options.operations,
|
3726
|
+
extensions: options.extensions,
|
3727
|
+
include: options.include,
|
3728
|
+
exclude: options.exclude,
|
3729
|
+
};
|
3730
|
+
graphQLConfig =
|
3731
|
+
onDiskConfig ||
|
3732
|
+
new graphqlConfig.GraphQLConfig({
|
3733
|
+
config: configOptions,
|
3734
|
+
filepath: 'virtual-config',
|
3735
|
+
}, [addCodeFileLoaderExtension]);
|
3736
|
+
return graphQLConfig;
|
3737
|
+
}
|
3738
|
+
const addCodeFileLoaderExtension = api => {
|
3739
|
+
api.loaders.schema.register(new codeFileLoader.CodeFileLoader());
|
3740
|
+
api.loaders.documents.register(new codeFileLoader.CodeFileLoader());
|
3741
|
+
return { name: 'graphql-eslint-loaders' };
|
3742
|
+
};
|
3743
|
+
|
3778
3744
|
let reachableTypesCache;
|
3779
3745
|
function getReachableTypes(schema) {
|
3780
3746
|
// We don't want cache reachableTypes on test environment
|
@@ -3857,7 +3823,7 @@ function parse(code, options) {
|
|
3857
3823
|
return parseForESLint(code, options).ast;
|
3858
3824
|
}
|
3859
3825
|
function parseForESLint(code, options = {}) {
|
3860
|
-
const gqlConfig =
|
3826
|
+
const gqlConfig = loadGraphQLConfig(options);
|
3861
3827
|
const schema = getSchema(options, gqlConfig);
|
3862
3828
|
const parserServices = {
|
3863
3829
|
hasTypeInfo: schema !== null,
|
package/index.mjs
CHANGED
@@ -4,10 +4,10 @@ import { statSync, existsSync, readFileSync } from 'fs';
|
|
4
4
|
import { dirname, extname, basename, relative, resolve } from 'path';
|
5
5
|
import { asArray, parseGraphQLSDL } from '@graphql-tools/utils';
|
6
6
|
import lowerCase from 'lodash.lowercase';
|
7
|
-
import { loadConfigSync, GraphQLConfig } from 'graphql-config';
|
8
|
-
import { CodeFileLoader } from '@graphql-tools/code-file-loader';
|
9
7
|
import depthLimit from 'graphql-depth-limit';
|
10
8
|
import { parseCode } from '@graphql-tools/graphql-tag-pluck';
|
9
|
+
import { loadConfigSync, GraphQLConfig } from 'graphql-config';
|
10
|
+
import { CodeFileLoader } from '@graphql-tools/code-file-loader';
|
11
11
|
import { RuleTester, Linter } from 'eslint';
|
12
12
|
import { codeFrameColumns } from '@babel/code-frame';
|
13
13
|
|
@@ -168,47 +168,6 @@ const configs = {
|
|
168
168
|
'operations-all': operationsAllConfig,
|
169
169
|
};
|
170
170
|
|
171
|
-
let graphQLConfig;
|
172
|
-
function loadCachedGraphQLConfig(options) {
|
173
|
-
// We don't want cache config on test environment
|
174
|
-
// Otherwise schema and documents will be same for all tests
|
175
|
-
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
176
|
-
return graphQLConfig;
|
177
|
-
}
|
178
|
-
graphQLConfig = loadGraphQLConfig(options);
|
179
|
-
return graphQLConfig;
|
180
|
-
}
|
181
|
-
function loadGraphQLConfig(options) {
|
182
|
-
const onDiskConfig = options.skipGraphQLConfig
|
183
|
-
? null
|
184
|
-
: loadConfigSync({
|
185
|
-
throwOnEmpty: false,
|
186
|
-
throwOnMissing: false,
|
187
|
-
extensions: [addCodeFileLoaderExtension],
|
188
|
-
});
|
189
|
-
const configOptions = options.projects
|
190
|
-
? { projects: options.projects }
|
191
|
-
: {
|
192
|
-
schema: (options.schema || ''),
|
193
|
-
documents: options.documents || options.operations,
|
194
|
-
extensions: options.extensions,
|
195
|
-
include: options.include,
|
196
|
-
exclude: options.exclude,
|
197
|
-
};
|
198
|
-
graphQLConfig =
|
199
|
-
onDiskConfig ||
|
200
|
-
new GraphQLConfig({
|
201
|
-
config: configOptions,
|
202
|
-
filepath: 'virtual-config',
|
203
|
-
}, [addCodeFileLoaderExtension]);
|
204
|
-
return graphQLConfig;
|
205
|
-
}
|
206
|
-
const addCodeFileLoaderExtension = api => {
|
207
|
-
api.loaders.schema.register(new CodeFileLoader());
|
208
|
-
api.loaders.documents.register(new CodeFileLoader());
|
209
|
-
return { name: 'graphql-eslint-loaders' };
|
210
|
-
};
|
211
|
-
|
212
171
|
function requireSiblingsOperations(ruleName, context) {
|
213
172
|
if (!context.parserServices) {
|
214
173
|
throw new Error(`Rule '${ruleName}' requires 'parserOptions.operations' to be set and loaded. See http://bit.ly/graphql-eslint-operations for more info`);
|
@@ -227,32 +186,6 @@ function requireGraphQLSchemaFromContext(ruleName, context) {
|
|
227
186
|
}
|
228
187
|
return context.parserServices.schema;
|
229
188
|
}
|
230
|
-
const schemaToExtendCache = new Map();
|
231
|
-
function getGraphQLSchemaToExtend(context) {
|
232
|
-
// If parserOptions.schema not set or not loaded, there is no reason to make partial schema aka schemaToExtend
|
233
|
-
if (!context.parserServices.hasTypeInfo) {
|
234
|
-
return null;
|
235
|
-
}
|
236
|
-
const filename = context.getPhysicalFilename();
|
237
|
-
if (!schemaToExtendCache.has(filename)) {
|
238
|
-
const { schema, schemaOptions } = context.parserOptions;
|
239
|
-
const gqlConfig = loadGraphQLConfig({ schema });
|
240
|
-
const projectForFile = gqlConfig.getProjectForFile(filename);
|
241
|
-
let schemaToExtend;
|
242
|
-
try {
|
243
|
-
schemaToExtend = projectForFile.loadSchemaSync(projectForFile.schema, 'GraphQLSchema', {
|
244
|
-
...schemaOptions,
|
245
|
-
ignore: filename,
|
246
|
-
});
|
247
|
-
}
|
248
|
-
catch (_a) {
|
249
|
-
// If error throws just ignore it because maybe schema is located in 1 file
|
250
|
-
schemaToExtend = null;
|
251
|
-
}
|
252
|
-
schemaToExtendCache.set(filename, schemaToExtend);
|
253
|
-
}
|
254
|
-
return schemaToExtendCache.get(filename);
|
255
|
-
}
|
256
189
|
function requireReachableTypesFromContext(ruleName, context) {
|
257
190
|
const schema = requireGraphQLSchemaFromContext(ruleName, context);
|
258
191
|
return context.parserServices.reachableTypes(schema);
|
@@ -387,7 +320,7 @@ function getLocation(loc, fieldName = '', offset) {
|
|
387
320
|
};
|
388
321
|
}
|
389
322
|
|
390
|
-
function validateDocument(
|
323
|
+
function validateDocument(context, schema = null, documentNode, rule, isSchemaToExtend = false) {
|
391
324
|
if (documentNode.definitions.length === 0) {
|
392
325
|
return;
|
393
326
|
}
|
@@ -419,7 +352,8 @@ function validateDocument(sourceNode, context, schema = null, documentNode, rule
|
|
419
352
|
}
|
420
353
|
catch (e) {
|
421
354
|
context.report({
|
422
|
-
|
355
|
+
// Report on first character
|
356
|
+
loc: { column: 0, line: 1 },
|
423
357
|
message: e.message,
|
424
358
|
});
|
425
359
|
}
|
@@ -506,19 +440,13 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode) => {
|
|
506
440
|
console.warn(`You rule "${ruleId}" depends on a GraphQL validation rule "${ruleName}" but it's not available in the "graphql-js" version you are using. Skipping...`);
|
507
441
|
return {};
|
508
442
|
}
|
509
|
-
|
510
|
-
if (docs.requiresSchemaToExtend) {
|
511
|
-
schema = getGraphQLSchemaToExtend(context);
|
512
|
-
}
|
513
|
-
if (docs.requiresSchema) {
|
514
|
-
schema = requireGraphQLSchemaFromContext(ruleId, context);
|
515
|
-
}
|
443
|
+
const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
|
516
444
|
return {
|
517
445
|
Document(node) {
|
518
446
|
const documentNode = getDocumentNode
|
519
447
|
? getDocumentNode({ ruleId, context, schema, node: node.rawNode() })
|
520
448
|
: node.rawNode();
|
521
|
-
validateDocument(
|
449
|
+
validateDocument(context, schema, documentNode, ruleFn, docs.requiresSchemaToExtend);
|
522
450
|
},
|
523
451
|
};
|
524
452
|
},
|
@@ -669,6 +597,7 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
669
597
|
category: 'Schema',
|
670
598
|
description: `A type extension is only valid if the type is defined and has the same kind.`,
|
671
599
|
recommended: false,
|
600
|
+
requiresSchema: true,
|
672
601
|
requiresSchemaToExtend: true,
|
673
602
|
}), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
|
674
603
|
category: ['Schema', 'Operations'],
|
@@ -3769,6 +3698,43 @@ function getSiblingOperations(options, gqlConfig) {
|
|
3769
3698
|
return siblingOperations;
|
3770
3699
|
}
|
3771
3700
|
|
3701
|
+
let graphQLConfig;
|
3702
|
+
function loadGraphQLConfig(options) {
|
3703
|
+
// We don't want cache config on test environment
|
3704
|
+
// Otherwise schema and documents will be same for all tests
|
3705
|
+
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
3706
|
+
return graphQLConfig;
|
3707
|
+
}
|
3708
|
+
const onDiskConfig = options.skipGraphQLConfig
|
3709
|
+
? null
|
3710
|
+
: loadConfigSync({
|
3711
|
+
throwOnEmpty: false,
|
3712
|
+
throwOnMissing: false,
|
3713
|
+
extensions: [addCodeFileLoaderExtension],
|
3714
|
+
});
|
3715
|
+
const configOptions = options.projects
|
3716
|
+
? { projects: options.projects }
|
3717
|
+
: {
|
3718
|
+
schema: (options.schema || ''),
|
3719
|
+
documents: options.documents || options.operations,
|
3720
|
+
extensions: options.extensions,
|
3721
|
+
include: options.include,
|
3722
|
+
exclude: options.exclude,
|
3723
|
+
};
|
3724
|
+
graphQLConfig =
|
3725
|
+
onDiskConfig ||
|
3726
|
+
new GraphQLConfig({
|
3727
|
+
config: configOptions,
|
3728
|
+
filepath: 'virtual-config',
|
3729
|
+
}, [addCodeFileLoaderExtension]);
|
3730
|
+
return graphQLConfig;
|
3731
|
+
}
|
3732
|
+
const addCodeFileLoaderExtension = api => {
|
3733
|
+
api.loaders.schema.register(new CodeFileLoader());
|
3734
|
+
api.loaders.documents.register(new CodeFileLoader());
|
3735
|
+
return { name: 'graphql-eslint-loaders' };
|
3736
|
+
};
|
3737
|
+
|
3772
3738
|
let reachableTypesCache;
|
3773
3739
|
function getReachableTypes(schema) {
|
3774
3740
|
// We don't want cache reachableTypes on test environment
|
@@ -3851,7 +3817,7 @@ function parse(code, options) {
|
|
3851
3817
|
return parseForESLint(code, options).ast;
|
3852
3818
|
}
|
3853
3819
|
function parseForESLint(code, options = {}) {
|
3854
|
-
const gqlConfig =
|
3820
|
+
const gqlConfig = loadGraphQLConfig(options);
|
3855
3821
|
const schema = getSchema(options, gqlConfig);
|
3856
3822
|
const parserServices = {
|
3857
3823
|
hasTypeInfo: schema !== null,
|
package/package.json
CHANGED
package/utils.d.ts
CHANGED
@@ -6,7 +6,6 @@ import { SiblingOperations } from './sibling-operations';
|
|
6
6
|
import { UsedFields, ReachableTypes } from './graphql-ast';
|
7
7
|
export declare function requireSiblingsOperations(ruleName: string, context: GraphQLESLintRuleContext): SiblingOperations | never;
|
8
8
|
export declare function requireGraphQLSchemaFromContext(ruleName: string, context: GraphQLESLintRuleContext): GraphQLSchema | never;
|
9
|
-
export declare function getGraphQLSchemaToExtend(context: GraphQLESLintRuleContext): GraphQLSchema | null;
|
10
9
|
export declare function requireReachableTypesFromContext(ruleName: string, context: GraphQLESLintRuleContext): ReachableTypes | never;
|
11
10
|
export declare function requireUsedFieldsFromContext(ruleName: string, context: GraphQLESLintRuleContext): UsedFields | never;
|
12
11
|
export declare function extractTokens(source: Source): AST.Token[];
|