@graphql-eslint/eslint-plugin 3.3.0-alpha-db2c2cb.0 → 3.3.0-alpha-1c01242.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 +1 -1
- package/index.js +47 -35
- package/index.mjs +44 -32
- package/package.json +3 -2
- package/types.d.ts +1 -0
@@ -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
@@ -12,7 +12,7 @@ const utils = require('@graphql-tools/utils');
|
|
12
12
|
const lowerCase = _interopDefault(require('lodash.lowercase'));
|
13
13
|
const depthLimit = _interopDefault(require('graphql-depth-limit'));
|
14
14
|
const graphqlTagPluck = require('@graphql-tools/graphql-tag-pluck');
|
15
|
-
const graphqlConfig
|
15
|
+
const graphqlConfig = require('graphql-config');
|
16
16
|
const codeFileLoader = require('@graphql-tools/code-file-loader');
|
17
17
|
const eslint = require('eslint');
|
18
18
|
const codeFrame = require('@babel/code-frame');
|
@@ -326,14 +326,14 @@ function getLocation(loc, fieldName = '', offset) {
|
|
326
326
|
};
|
327
327
|
}
|
328
328
|
|
329
|
-
function validateDocument(
|
329
|
+
function validateDocument(context, schema = null, documentNode, rule, isSchemaToExtend = false) {
|
330
330
|
if (documentNode.definitions.length === 0) {
|
331
331
|
return;
|
332
332
|
}
|
333
333
|
try {
|
334
|
-
const validationErrors = schema
|
334
|
+
const validationErrors = schema && !isSchemaToExtend
|
335
335
|
? graphql.validate(schema, documentNode, [rule])
|
336
|
-
: validate.validateSDL(documentNode,
|
336
|
+
: validate.validateSDL(documentNode, schema, [rule]);
|
337
337
|
for (const error of validationErrors) {
|
338
338
|
/*
|
339
339
|
* TODO: Fix ESTree-AST converter because currently it's incorrectly convert loc.end
|
@@ -358,7 +358,8 @@ function validateDocument(sourceNode, context, schema, documentNode, rule) {
|
|
358
358
|
}
|
359
359
|
catch (e) {
|
360
360
|
context.report({
|
361
|
-
|
361
|
+
// Report on first character
|
362
|
+
loc: { column: 0, line: 1 },
|
362
363
|
message: e.message,
|
363
364
|
});
|
364
365
|
}
|
@@ -440,18 +441,18 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode) => {
|
|
440
441
|
},
|
441
442
|
},
|
442
443
|
create(context) {
|
444
|
+
if (!ruleFn) {
|
445
|
+
// eslint-disable-next-line no-console
|
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...`);
|
447
|
+
return {};
|
448
|
+
}
|
449
|
+
const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
|
443
450
|
return {
|
444
451
|
Document(node) {
|
445
|
-
if (!ruleFn) {
|
446
|
-
// eslint-disable-next-line no-console
|
447
|
-
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...`);
|
448
|
-
return;
|
449
|
-
}
|
450
|
-
const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
|
451
452
|
const documentNode = getDocumentNode
|
452
453
|
? getDocumentNode({ ruleId, context, schema, node: node.rawNode() })
|
453
454
|
: node.rawNode();
|
454
|
-
validateDocument(
|
455
|
+
validateDocument(context, schema, documentNode, ruleFn, docs.requiresSchemaToExtend);
|
455
456
|
},
|
456
457
|
};
|
457
458
|
},
|
@@ -601,7 +602,9 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
601
602
|
}), validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
|
602
603
|
category: 'Schema',
|
603
604
|
description: `A type extension is only valid if the type is defined and has the same kind.`,
|
604
|
-
recommended: false,
|
605
|
+
recommended: false,
|
606
|
+
requiresSchema: true,
|
607
|
+
requiresSchemaToExtend: true,
|
605
608
|
}), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
|
606
609
|
category: ['Schema', 'Operations'],
|
607
610
|
description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
|
@@ -3701,35 +3704,36 @@ function getSiblingOperations(options, gqlConfig) {
|
|
3701
3704
|
return siblingOperations;
|
3702
3705
|
}
|
3703
3706
|
|
3704
|
-
let
|
3705
|
-
function
|
3707
|
+
let graphQLConfig;
|
3708
|
+
function loadGraphQLConfig(options) {
|
3706
3709
|
// We don't want cache config on test environment
|
3707
3710
|
// Otherwise schema and documents will be same for all tests
|
3708
|
-
if (process.env.NODE_ENV !== 'test' &&
|
3709
|
-
return
|
3711
|
+
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
3712
|
+
return graphQLConfig;
|
3710
3713
|
}
|
3711
3714
|
const onDiskConfig = options.skipGraphQLConfig
|
3712
3715
|
? null
|
3713
|
-
: graphqlConfig
|
3716
|
+
: graphqlConfig.loadConfigSync({
|
3714
3717
|
throwOnEmpty: false,
|
3715
3718
|
throwOnMissing: false,
|
3716
3719
|
extensions: [addCodeFileLoaderExtension],
|
3717
3720
|
});
|
3718
|
-
|
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 =
|
3719
3731
|
onDiskConfig ||
|
3720
|
-
new graphqlConfig
|
3721
|
-
config:
|
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
|
-
},
|
3732
|
+
new graphqlConfig.GraphQLConfig({
|
3733
|
+
config: configOptions,
|
3730
3734
|
filepath: 'virtual-config',
|
3731
3735
|
}, [addCodeFileLoaderExtension]);
|
3732
|
-
return
|
3736
|
+
return graphQLConfig;
|
3733
3737
|
}
|
3734
3738
|
const addCodeFileLoaderExtension = api => {
|
3735
3739
|
api.loaders.schema.register(new codeFileLoader.CodeFileLoader());
|
@@ -3819,10 +3823,18 @@ function parse(code, options) {
|
|
3819
3823
|
return parseForESLint(code, options).ast;
|
3820
3824
|
}
|
3821
3825
|
function parseForESLint(code, options = {}) {
|
3822
|
-
const gqlConfig =
|
3823
|
-
|
3826
|
+
const gqlConfig = loadGraphQLConfig(options);
|
3827
|
+
let schema;
|
3828
|
+
try {
|
3829
|
+
schema = getSchema(options, gqlConfig);
|
3830
|
+
}
|
3831
|
+
catch (e) {
|
3832
|
+
e.message = `[graphql-eslint] Error while loading schema: ${e.message}`;
|
3833
|
+
// eslint-disable-next-line no-console
|
3834
|
+
console.error(e);
|
3835
|
+
}
|
3824
3836
|
const parserServices = {
|
3825
|
-
hasTypeInfo: schema
|
3837
|
+
hasTypeInfo: Boolean(schema),
|
3826
3838
|
schema,
|
3827
3839
|
siblingOperations: getSiblingOperations(options, gqlConfig),
|
3828
3840
|
reachableTypes: getReachableTypes,
|
@@ -3851,6 +3863,7 @@ function parseForESLint(code, options = {}) {
|
|
3851
3863
|
};
|
3852
3864
|
}
|
3853
3865
|
catch (e) {
|
3866
|
+
e.message = `[graphql-eslint] ${e.message}`;
|
3854
3867
|
// In case of GraphQL parser error, we report it to ESLint as a parser error that matches the requirements
|
3855
3868
|
// of ESLint. This will make sure to display it correctly in IDEs and lint results.
|
3856
3869
|
if (e instanceof graphql.GraphQLError) {
|
@@ -3858,11 +3871,10 @@ function parseForESLint(code, options = {}) {
|
|
3858
3871
|
index: e.positions[0],
|
3859
3872
|
lineNumber: e.locations[0].line,
|
3860
3873
|
column: e.locations[0].column,
|
3861
|
-
message:
|
3874
|
+
message: e.message,
|
3862
3875
|
};
|
3863
3876
|
throw eslintError;
|
3864
3877
|
}
|
3865
|
-
e.message = `[graphql-eslint]: ${e.message}`;
|
3866
3878
|
throw e;
|
3867
3879
|
}
|
3868
3880
|
}
|
package/index.mjs
CHANGED
@@ -320,14 +320,14 @@ function getLocation(loc, fieldName = '', offset) {
|
|
320
320
|
};
|
321
321
|
}
|
322
322
|
|
323
|
-
function validateDocument(
|
323
|
+
function validateDocument(context, schema = null, documentNode, rule, isSchemaToExtend = false) {
|
324
324
|
if (documentNode.definitions.length === 0) {
|
325
325
|
return;
|
326
326
|
}
|
327
327
|
try {
|
328
|
-
const validationErrors = schema
|
328
|
+
const validationErrors = schema && !isSchemaToExtend
|
329
329
|
? validate(schema, documentNode, [rule])
|
330
|
-
: validateSDL(documentNode,
|
330
|
+
: validateSDL(documentNode, schema, [rule]);
|
331
331
|
for (const error of validationErrors) {
|
332
332
|
/*
|
333
333
|
* TODO: Fix ESTree-AST converter because currently it's incorrectly convert loc.end
|
@@ -352,7 +352,8 @@ function validateDocument(sourceNode, context, schema, documentNode, rule) {
|
|
352
352
|
}
|
353
353
|
catch (e) {
|
354
354
|
context.report({
|
355
|
-
|
355
|
+
// Report on first character
|
356
|
+
loc: { column: 0, line: 1 },
|
356
357
|
message: e.message,
|
357
358
|
});
|
358
359
|
}
|
@@ -434,18 +435,18 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode) => {
|
|
434
435
|
},
|
435
436
|
},
|
436
437
|
create(context) {
|
438
|
+
if (!ruleFn) {
|
439
|
+
// eslint-disable-next-line no-console
|
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...`);
|
441
|
+
return {};
|
442
|
+
}
|
443
|
+
const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
|
437
444
|
return {
|
438
445
|
Document(node) {
|
439
|
-
if (!ruleFn) {
|
440
|
-
// eslint-disable-next-line no-console
|
441
|
-
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...`);
|
442
|
-
return;
|
443
|
-
}
|
444
|
-
const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
|
445
446
|
const documentNode = getDocumentNode
|
446
447
|
? getDocumentNode({ ruleId, context, schema, node: node.rawNode() })
|
447
448
|
: node.rawNode();
|
448
|
-
validateDocument(
|
449
|
+
validateDocument(context, schema, documentNode, ruleFn, docs.requiresSchemaToExtend);
|
449
450
|
},
|
450
451
|
};
|
451
452
|
},
|
@@ -595,7 +596,9 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
595
596
|
}), validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
|
596
597
|
category: 'Schema',
|
597
598
|
description: `A type extension is only valid if the type is defined and has the same kind.`,
|
598
|
-
recommended: false,
|
599
|
+
recommended: false,
|
600
|
+
requiresSchema: true,
|
601
|
+
requiresSchemaToExtend: true,
|
599
602
|
}), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
|
600
603
|
category: ['Schema', 'Operations'],
|
601
604
|
description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
|
@@ -3695,12 +3698,12 @@ function getSiblingOperations(options, gqlConfig) {
|
|
3695
3698
|
return siblingOperations;
|
3696
3699
|
}
|
3697
3700
|
|
3698
|
-
let
|
3699
|
-
function
|
3701
|
+
let graphQLConfig;
|
3702
|
+
function loadGraphQLConfig(options) {
|
3700
3703
|
// We don't want cache config on test environment
|
3701
3704
|
// Otherwise schema and documents will be same for all tests
|
3702
|
-
if (process.env.NODE_ENV !== 'test' &&
|
3703
|
-
return
|
3705
|
+
if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
|
3706
|
+
return graphQLConfig;
|
3704
3707
|
}
|
3705
3708
|
const onDiskConfig = options.skipGraphQLConfig
|
3706
3709
|
? null
|
@@ -3709,21 +3712,22 @@ function loadGraphqlConfig(options) {
|
|
3709
3712
|
throwOnMissing: false,
|
3710
3713
|
extensions: [addCodeFileLoaderExtension],
|
3711
3714
|
});
|
3712
|
-
|
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 =
|
3713
3725
|
onDiskConfig ||
|
3714
3726
|
new GraphQLConfig({
|
3715
|
-
config:
|
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
|
-
},
|
3727
|
+
config: configOptions,
|
3724
3728
|
filepath: 'virtual-config',
|
3725
3729
|
}, [addCodeFileLoaderExtension]);
|
3726
|
-
return
|
3730
|
+
return graphQLConfig;
|
3727
3731
|
}
|
3728
3732
|
const addCodeFileLoaderExtension = api => {
|
3729
3733
|
api.loaders.schema.register(new CodeFileLoader());
|
@@ -3813,10 +3817,18 @@ function parse(code, options) {
|
|
3813
3817
|
return parseForESLint(code, options).ast;
|
3814
3818
|
}
|
3815
3819
|
function parseForESLint(code, options = {}) {
|
3816
|
-
const gqlConfig =
|
3817
|
-
|
3820
|
+
const gqlConfig = loadGraphQLConfig(options);
|
3821
|
+
let schema;
|
3822
|
+
try {
|
3823
|
+
schema = getSchema(options, gqlConfig);
|
3824
|
+
}
|
3825
|
+
catch (e) {
|
3826
|
+
e.message = `[graphql-eslint] Error while loading schema: ${e.message}`;
|
3827
|
+
// eslint-disable-next-line no-console
|
3828
|
+
console.error(e);
|
3829
|
+
}
|
3818
3830
|
const parserServices = {
|
3819
|
-
hasTypeInfo: schema
|
3831
|
+
hasTypeInfo: Boolean(schema),
|
3820
3832
|
schema,
|
3821
3833
|
siblingOperations: getSiblingOperations(options, gqlConfig),
|
3822
3834
|
reachableTypes: getReachableTypes,
|
@@ -3845,6 +3857,7 @@ function parseForESLint(code, options = {}) {
|
|
3845
3857
|
};
|
3846
3858
|
}
|
3847
3859
|
catch (e) {
|
3860
|
+
e.message = `[graphql-eslint] ${e.message}`;
|
3848
3861
|
// In case of GraphQL parser error, we report it to ESLint as a parser error that matches the requirements
|
3849
3862
|
// of ESLint. This will make sure to display it correctly in IDEs and lint results.
|
3850
3863
|
if (e instanceof GraphQLError) {
|
@@ -3852,11 +3865,10 @@ function parseForESLint(code, options = {}) {
|
|
3852
3865
|
index: e.positions[0],
|
3853
3866
|
lineNumber: e.locations[0].line,
|
3854
3867
|
column: e.locations[0].column,
|
3855
|
-
message:
|
3868
|
+
message: e.message,
|
3856
3869
|
};
|
3857
3870
|
throw eslintError;
|
3858
3871
|
}
|
3859
|
-
e.message = `[graphql-eslint]: ${e.message}`;
|
3860
3872
|
throw e;
|
3861
3873
|
}
|
3862
3874
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@graphql-eslint/eslint-plugin",
|
3
|
-
"version": "3.3.0-alpha-
|
3
|
+
"version": "3.3.0-alpha-1c01242.0",
|
4
4
|
"description": "GraphQL plugin for ESLint",
|
5
5
|
"sideEffects": false,
|
6
6
|
"peerDependencies": {
|
@@ -10,7 +10,7 @@
|
|
10
10
|
"@babel/code-frame": "7.16.0",
|
11
11
|
"@graphql-tools/code-file-loader": "7.2.3",
|
12
12
|
"@graphql-tools/graphql-tag-pluck": "7.1.4",
|
13
|
-
"@graphql-tools/utils": "8.5.
|
13
|
+
"@graphql-tools/utils": "8.5.5",
|
14
14
|
"graphql-config": "4.1.0",
|
15
15
|
"graphql-depth-limit": "1.1.0",
|
16
16
|
"lodash.lowercase": "4.3.0"
|
@@ -31,6 +31,7 @@
|
|
31
31
|
"definition": "index.d.ts"
|
32
32
|
},
|
33
33
|
"exports": {
|
34
|
+
"./package.json": "./package.json",
|
34
35
|
".": {
|
35
36
|
"require": "./index.js",
|
36
37
|
"import": "./index.mjs"
|