@graphql-eslint/eslint-plugin 3.2.0-alpha-2e742a6.0 → 3.2.0-alpha-6aa2721.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/index.js +53 -44
- package/index.mjs +53 -44
- package/package.json +8 -1
- package/types.d.ts +2 -2
package/index.js
CHANGED
@@ -334,7 +334,7 @@ function getLocation(loc, fieldName = '', offset) {
|
|
334
334
|
};
|
335
335
|
}
|
336
336
|
|
337
|
-
function
|
337
|
+
function validateDocument(sourceNode, context, schema, documentNode, rule) {
|
338
338
|
if (documentNode.definitions.length === 0) {
|
339
339
|
return;
|
340
340
|
}
|
@@ -365,9 +365,9 @@ const getFragmentDefsAndFragmentSpreads = (schema, node) => {
|
|
365
365
|
fragmentDefs.add(`${node.name.value}:${node.typeCondition.name.value}`);
|
366
366
|
},
|
367
367
|
FragmentSpread(node) {
|
368
|
-
const
|
369
|
-
if (
|
370
|
-
fragmentSpreads.add(`${node.name.value}:${
|
368
|
+
const parentType = typeInfo.getParentType();
|
369
|
+
if (parentType) {
|
370
|
+
fragmentSpreads.add(`${node.name.value}:${parentType.name}`);
|
371
371
|
}
|
372
372
|
},
|
373
373
|
});
|
@@ -378,7 +378,7 @@ const getMissingFragments = (schema, node) => {
|
|
378
378
|
const { fragmentDefs, fragmentSpreads } = getFragmentDefsAndFragmentSpreads(schema, node);
|
379
379
|
return [...fragmentSpreads].filter(name => !fragmentDefs.has(name));
|
380
380
|
};
|
381
|
-
const handleMissingFragments = ({
|
381
|
+
const handleMissingFragments = ({ ruleId, context, schema, node }) => {
|
382
382
|
const missingFragments = getMissingFragments(schema, node);
|
383
383
|
if (missingFragments.length > 0) {
|
384
384
|
const siblings = requireSiblingsOperations(ruleId, context);
|
@@ -389,45 +389,44 @@ const handleMissingFragments = ({ schema, node, ruleId, context }) => {
|
|
389
389
|
.getFragment(fragmentName)
|
390
390
|
.map(source => source.document)
|
391
391
|
.filter(fragment => fragment.typeCondition.name.value === fragmentTypeName);
|
392
|
-
if (fragments.length > 1) {
|
393
|
-
// eslint-disable-next-line no-console
|
394
|
-
console.warn(`You have ${fragments.length} fragments that have same name ${fragmentName} and same type ${fragmentTypeName}. That can provoke unexpected result for "${ruleId}" rule.`);
|
395
|
-
}
|
396
392
|
fragmentsToAdd.push(fragments[0]);
|
397
393
|
}
|
398
394
|
if (fragmentsToAdd.length > 0) {
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
395
|
+
// recall fn to make sure to add fragments inside fragments
|
396
|
+
return handleMissingFragments({
|
397
|
+
ruleId,
|
398
|
+
context,
|
399
|
+
schema,
|
400
|
+
node: {
|
401
|
+
kind: graphql.Kind.DOCUMENT,
|
402
|
+
definitions: [...node.definitions, ...fragmentsToAdd],
|
403
|
+
},
|
404
|
+
});
|
403
405
|
}
|
404
406
|
}
|
405
407
|
return node;
|
406
408
|
};
|
407
|
-
const validationToRule = (
|
408
|
-
var _a;
|
409
|
+
const validationToRule = (ruleId, ruleName, docs, getDocumentNode) => {
|
409
410
|
let ruleFn = null;
|
410
411
|
try {
|
411
412
|
ruleFn = require(`graphql/validation/rules/${ruleName}Rule`)[`${ruleName}Rule`];
|
412
413
|
}
|
413
|
-
catch (
|
414
|
+
catch (_a) {
|
414
415
|
try {
|
415
416
|
ruleFn = require(`graphql/validation/rules/${ruleName}`)[`${ruleName}Rule`];
|
416
417
|
}
|
417
|
-
catch (
|
418
|
+
catch (_b) {
|
418
419
|
ruleFn = require('graphql/validation')[`${ruleName}Rule`];
|
419
420
|
}
|
420
421
|
}
|
421
|
-
const requiresSchema = (_a = docs.requiresSchema) !== null && _a !== void 0 ? _a : true;
|
422
422
|
return {
|
423
|
-
[
|
423
|
+
[ruleId]: {
|
424
424
|
meta: {
|
425
425
|
docs: {
|
426
426
|
recommended: true,
|
427
427
|
...docs,
|
428
428
|
graphQLJSRuleName: ruleName,
|
429
|
-
|
430
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${name}.md`,
|
429
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${ruleId}.md`,
|
431
430
|
description: `${docs.description}\n\n> This rule is a wrapper around a \`graphql-js\` validation function. [You can find its source code here](https://github.com/graphql/graphql-js/blob/main/src/validation/rules/${ruleName}Rule.ts).`,
|
432
431
|
},
|
433
432
|
},
|
@@ -436,19 +435,14 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
|
|
436
435
|
Document(node) {
|
437
436
|
if (!ruleFn) {
|
438
437
|
// eslint-disable-next-line no-console
|
439
|
-
console.warn(`You rule "${
|
438
|
+
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...`);
|
440
439
|
return;
|
441
440
|
}
|
442
|
-
const schema = requiresSchema ? requireGraphQLSchemaFromContext(
|
443
|
-
const documentNode =
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
node: documentNode,
|
448
|
-
ruleId: name,
|
449
|
-
context,
|
450
|
-
})
|
451
|
-
: documentNode, ruleFn);
|
441
|
+
const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
|
442
|
+
const documentNode = getDocumentNode
|
443
|
+
? getDocumentNode({ ruleId, context, schema, node: node.rawNode() })
|
444
|
+
: node.rawNode();
|
445
|
+
validateDocument(node, context, schema, documentNode, ruleFn);
|
452
446
|
},
|
453
447
|
};
|
454
448
|
},
|
@@ -458,21 +452,27 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
|
|
458
452
|
const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-definitions', 'ExecutableDefinitions', {
|
459
453
|
category: 'Operations',
|
460
454
|
description: `A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.`,
|
455
|
+
requiresSchema: true,
|
461
456
|
}), validationToRule('fields-on-correct-type', 'FieldsOnCorrectType', {
|
462
457
|
category: 'Operations',
|
463
458
|
description: 'A GraphQL document is only valid if all fields selected are defined by the parent type, or are an allowed meta field such as `__typename`.',
|
459
|
+
requiresSchema: true,
|
464
460
|
}), validationToRule('fragments-on-composite-type', 'FragmentsOnCompositeTypes', {
|
465
461
|
category: 'Operations',
|
466
462
|
description: `Fragments use a type condition to determine if they apply, since fragments can only be spread into a composite type (object, interface, or union), the type condition must also be a composite type.`,
|
463
|
+
requiresSchema: true,
|
467
464
|
}), validationToRule('known-argument-names', 'KnownArgumentNames', {
|
468
465
|
category: ['Schema', 'Operations'],
|
469
466
|
description: `A GraphQL field is only valid if all supplied arguments are defined by that field.`,
|
467
|
+
requiresSchema: true,
|
470
468
|
}), validationToRule('known-directives', 'KnownDirectives', {
|
471
469
|
category: ['Schema', 'Operations'],
|
472
470
|
description: `A GraphQL document is only valid if all \`@directives\` are known by the schema and legally positioned.`,
|
471
|
+
requiresSchema: true,
|
473
472
|
}), validationToRule('known-fragment-names', 'KnownFragmentNames', {
|
474
473
|
category: 'Operations',
|
475
474
|
description: `A GraphQL document is only valid if all \`...Fragment\` fragment spreads refer to fragments defined in the same document.`,
|
475
|
+
requiresSchema: true,
|
476
476
|
requiresSiblings: true,
|
477
477
|
examples: [
|
478
478
|
{
|
@@ -523,27 +523,31 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
523
523
|
}, handleMissingFragments), validationToRule('known-type-names', 'KnownTypeNames', {
|
524
524
|
category: ['Schema', 'Operations'],
|
525
525
|
description: `A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.`,
|
526
|
+
requiresSchema: true,
|
526
527
|
}), validationToRule('lone-anonymous-operation', 'LoneAnonymousOperation', {
|
527
528
|
category: 'Operations',
|
528
529
|
description: `A GraphQL document is only valid if when it contains an anonymous operation (the query short-hand) that it contains only that one operation definition.`,
|
530
|
+
requiresSchema: true,
|
529
531
|
}), validationToRule('lone-schema-definition', 'LoneSchemaDefinition', {
|
530
532
|
category: 'Schema',
|
531
533
|
description: `A GraphQL document is only valid if it contains only one schema definition.`,
|
532
|
-
requiresSchema: false,
|
533
534
|
}), validationToRule('no-fragment-cycles', 'NoFragmentCycles', {
|
534
535
|
category: 'Operations',
|
535
536
|
description: `A GraphQL fragment is only valid when it does not have cycles in fragments usage.`,
|
537
|
+
requiresSchema: true,
|
536
538
|
}), validationToRule('no-undefined-variables', 'NoUndefinedVariables', {
|
537
539
|
category: 'Operations',
|
538
540
|
description: `A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.`,
|
541
|
+
requiresSchema: true,
|
539
542
|
requiresSiblings: true,
|
540
543
|
}, handleMissingFragments), validationToRule('no-unused-fragments', 'NoUnusedFragments', {
|
541
544
|
category: 'Operations',
|
542
545
|
description: `A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.`,
|
546
|
+
requiresSchema: true,
|
543
547
|
requiresSiblings: true,
|
544
|
-
}, ({
|
548
|
+
}, ({ ruleId, context, schema, node }) => {
|
545
549
|
const siblings = requireSiblingsOperations(ruleId, context);
|
546
|
-
const
|
550
|
+
const FilePathToDocumentsMap = [...siblings.getOperations(), ...siblings.getFragments()].reduce((map, { filePath, document }) => {
|
547
551
|
var _a;
|
548
552
|
(_a = map[filePath]) !== null && _a !== void 0 ? _a : (map[filePath] = []);
|
549
553
|
map[filePath].push(document);
|
@@ -555,8 +559,8 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
555
559
|
return node;
|
556
560
|
}
|
557
561
|
// skip iteration over documents for current filepath
|
558
|
-
delete
|
559
|
-
for (const [filePath, documents] of Object.entries(
|
562
|
+
delete FilePathToDocumentsMap[currentFilePath];
|
563
|
+
for (const [filePath, documents] of Object.entries(FilePathToDocumentsMap)) {
|
560
564
|
const missingFragments = getMissingFragments(schema, {
|
561
565
|
kind: graphql.Kind.DOCUMENT,
|
562
566
|
definitions: documents,
|
@@ -575,70 +579,75 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
575
579
|
}), validationToRule('no-unused-variables', 'NoUnusedVariables', {
|
576
580
|
category: 'Operations',
|
577
581
|
description: `A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.`,
|
582
|
+
requiresSchema: true,
|
578
583
|
requiresSiblings: true,
|
579
584
|
}, handleMissingFragments), validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
|
580
585
|
category: 'Operations',
|
581
586
|
description: `A selection set is only valid if all fields (including spreading any fragments) either correspond to distinct response names or can be merged without ambiguity.`,
|
587
|
+
requiresSchema: true,
|
582
588
|
}), validationToRule('possible-fragment-spread', 'PossibleFragmentSpreads', {
|
583
589
|
category: 'Operations',
|
584
590
|
description: `A fragment spread is only valid if the type condition could ever possibly be true: if there is a non-empty intersection of the possible parent types, and possible types which pass the type condition.`,
|
591
|
+
requiresSchema: true,
|
585
592
|
}), validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
|
586
593
|
category: 'Schema',
|
587
594
|
description: `A type extension is only valid if the type is defined and has the same kind.`,
|
588
|
-
requiresSchema: false,
|
589
595
|
recommended: false, // TODO: enable after https://github.com/dotansimha/graphql-eslint/issues/787 will be fixed
|
590
596
|
}), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
|
591
597
|
category: ['Schema', 'Operations'],
|
592
598
|
description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
|
599
|
+
requiresSchema: true,
|
593
600
|
}), validationToRule('scalar-leafs', 'ScalarLeafs', {
|
594
601
|
category: 'Operations',
|
595
602
|
description: `A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.`,
|
603
|
+
requiresSchema: true,
|
596
604
|
}), validationToRule('one-field-subscriptions', 'SingleFieldSubscriptions', {
|
597
605
|
category: 'Operations',
|
598
606
|
description: `A GraphQL subscription is valid only if it contains a single root field.`,
|
607
|
+
requiresSchema: true,
|
599
608
|
}), validationToRule('unique-argument-names', 'UniqueArgumentNames', {
|
600
609
|
category: 'Operations',
|
601
610
|
description: `A GraphQL field or directive is only valid if all supplied arguments are uniquely named.`,
|
611
|
+
requiresSchema: true,
|
602
612
|
}), validationToRule('unique-directive-names', 'UniqueDirectiveNames', {
|
603
613
|
category: 'Schema',
|
604
614
|
description: `A GraphQL document is only valid if all defined directives have unique names.`,
|
605
|
-
requiresSchema: false,
|
606
615
|
}), validationToRule('unique-directive-names-per-location', 'UniqueDirectivesPerLocation', {
|
607
616
|
category: ['Schema', 'Operations'],
|
608
617
|
description: `A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.`,
|
618
|
+
requiresSchema: true,
|
609
619
|
}), validationToRule('unique-enum-value-names', 'UniqueEnumValueNames', {
|
610
620
|
category: 'Schema',
|
611
621
|
description: `A GraphQL enum type is only valid if all its values are uniquely named.`,
|
612
|
-
requiresSchema: false,
|
613
622
|
recommended: false,
|
614
623
|
}), validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
|
615
624
|
category: 'Schema',
|
616
625
|
description: `A GraphQL complex type is only valid if all its fields are uniquely named.`,
|
617
|
-
requiresSchema: false,
|
618
626
|
}), validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
|
619
627
|
category: 'Operations',
|
620
628
|
description: `A GraphQL input object value is only valid if all supplied fields are uniquely named.`,
|
621
|
-
requiresSchema: false,
|
622
629
|
}), validationToRule('unique-operation-types', 'UniqueOperationTypes', {
|
623
630
|
category: 'Schema',
|
624
631
|
description: `A GraphQL document is only valid if it has only one type per operation.`,
|
625
|
-
requiresSchema: false,
|
626
632
|
}), validationToRule('unique-type-names', 'UniqueTypeNames', {
|
627
633
|
category: 'Schema',
|
628
634
|
description: `A GraphQL document is only valid if all defined types have unique names.`,
|
629
|
-
requiresSchema: false,
|
630
635
|
}), validationToRule('unique-variable-names', 'UniqueVariableNames', {
|
631
636
|
category: 'Operations',
|
632
637
|
description: `A GraphQL operation is only valid if all its variables are uniquely named.`,
|
638
|
+
requiresSchema: true,
|
633
639
|
}), validationToRule('value-literals-of-correct-type', 'ValuesOfCorrectType', {
|
634
640
|
category: 'Operations',
|
635
641
|
description: `A GraphQL document is only valid if all value literals are of the type expected at their position.`,
|
642
|
+
requiresSchema: true,
|
636
643
|
}), validationToRule('variables-are-input-types', 'VariablesAreInputTypes', {
|
637
644
|
category: 'Operations',
|
638
645
|
description: `A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).`,
|
646
|
+
requiresSchema: true,
|
639
647
|
}), validationToRule('variables-in-allowed-position', 'VariablesInAllowedPosition', {
|
640
648
|
category: 'Operations',
|
641
649
|
description: `Variables passed to field arguments conform to type.`,
|
650
|
+
requiresSchema: true,
|
642
651
|
}));
|
643
652
|
|
644
653
|
const ALPHABETIZE = 'ALPHABETIZE';
|
package/index.mjs
CHANGED
@@ -328,7 +328,7 @@ function getLocation(loc, fieldName = '', offset) {
|
|
328
328
|
};
|
329
329
|
}
|
330
330
|
|
331
|
-
function
|
331
|
+
function validateDocument(sourceNode, context, schema, documentNode, rule) {
|
332
332
|
if (documentNode.definitions.length === 0) {
|
333
333
|
return;
|
334
334
|
}
|
@@ -359,9 +359,9 @@ const getFragmentDefsAndFragmentSpreads = (schema, node) => {
|
|
359
359
|
fragmentDefs.add(`${node.name.value}:${node.typeCondition.name.value}`);
|
360
360
|
},
|
361
361
|
FragmentSpread(node) {
|
362
|
-
const
|
363
|
-
if (
|
364
|
-
fragmentSpreads.add(`${node.name.value}:${
|
362
|
+
const parentType = typeInfo.getParentType();
|
363
|
+
if (parentType) {
|
364
|
+
fragmentSpreads.add(`${node.name.value}:${parentType.name}`);
|
365
365
|
}
|
366
366
|
},
|
367
367
|
});
|
@@ -372,7 +372,7 @@ const getMissingFragments = (schema, node) => {
|
|
372
372
|
const { fragmentDefs, fragmentSpreads } = getFragmentDefsAndFragmentSpreads(schema, node);
|
373
373
|
return [...fragmentSpreads].filter(name => !fragmentDefs.has(name));
|
374
374
|
};
|
375
|
-
const handleMissingFragments = ({
|
375
|
+
const handleMissingFragments = ({ ruleId, context, schema, node }) => {
|
376
376
|
const missingFragments = getMissingFragments(schema, node);
|
377
377
|
if (missingFragments.length > 0) {
|
378
378
|
const siblings = requireSiblingsOperations(ruleId, context);
|
@@ -383,45 +383,44 @@ const handleMissingFragments = ({ schema, node, ruleId, context }) => {
|
|
383
383
|
.getFragment(fragmentName)
|
384
384
|
.map(source => source.document)
|
385
385
|
.filter(fragment => fragment.typeCondition.name.value === fragmentTypeName);
|
386
|
-
if (fragments.length > 1) {
|
387
|
-
// eslint-disable-next-line no-console
|
388
|
-
console.warn(`You have ${fragments.length} fragments that have same name ${fragmentName} and same type ${fragmentTypeName}. That can provoke unexpected result for "${ruleId}" rule.`);
|
389
|
-
}
|
390
386
|
fragmentsToAdd.push(fragments[0]);
|
391
387
|
}
|
392
388
|
if (fragmentsToAdd.length > 0) {
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
389
|
+
// recall fn to make sure to add fragments inside fragments
|
390
|
+
return handleMissingFragments({
|
391
|
+
ruleId,
|
392
|
+
context,
|
393
|
+
schema,
|
394
|
+
node: {
|
395
|
+
kind: Kind.DOCUMENT,
|
396
|
+
definitions: [...node.definitions, ...fragmentsToAdd],
|
397
|
+
},
|
398
|
+
});
|
397
399
|
}
|
398
400
|
}
|
399
401
|
return node;
|
400
402
|
};
|
401
|
-
const validationToRule = (
|
402
|
-
var _a;
|
403
|
+
const validationToRule = (ruleId, ruleName, docs, getDocumentNode) => {
|
403
404
|
let ruleFn = null;
|
404
405
|
try {
|
405
406
|
ruleFn = require(`graphql/validation/rules/${ruleName}Rule`)[`${ruleName}Rule`];
|
406
407
|
}
|
407
|
-
catch (
|
408
|
+
catch (_a) {
|
408
409
|
try {
|
409
410
|
ruleFn = require(`graphql/validation/rules/${ruleName}`)[`${ruleName}Rule`];
|
410
411
|
}
|
411
|
-
catch (
|
412
|
+
catch (_b) {
|
412
413
|
ruleFn = require('graphql/validation')[`${ruleName}Rule`];
|
413
414
|
}
|
414
415
|
}
|
415
|
-
const requiresSchema = (_a = docs.requiresSchema) !== null && _a !== void 0 ? _a : true;
|
416
416
|
return {
|
417
|
-
[
|
417
|
+
[ruleId]: {
|
418
418
|
meta: {
|
419
419
|
docs: {
|
420
420
|
recommended: true,
|
421
421
|
...docs,
|
422
422
|
graphQLJSRuleName: ruleName,
|
423
|
-
|
424
|
-
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${name}.md`,
|
423
|
+
url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${ruleId}.md`,
|
425
424
|
description: `${docs.description}\n\n> This rule is a wrapper around a \`graphql-js\` validation function. [You can find its source code here](https://github.com/graphql/graphql-js/blob/main/src/validation/rules/${ruleName}Rule.ts).`,
|
426
425
|
},
|
427
426
|
},
|
@@ -430,19 +429,14 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
|
|
430
429
|
Document(node) {
|
431
430
|
if (!ruleFn) {
|
432
431
|
// eslint-disable-next-line no-console
|
433
|
-
console.warn(`You rule "${
|
432
|
+
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...`);
|
434
433
|
return;
|
435
434
|
}
|
436
|
-
const schema = requiresSchema ? requireGraphQLSchemaFromContext(
|
437
|
-
const documentNode =
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
node: documentNode,
|
442
|
-
ruleId: name,
|
443
|
-
context,
|
444
|
-
})
|
445
|
-
: documentNode, ruleFn);
|
435
|
+
const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
|
436
|
+
const documentNode = getDocumentNode
|
437
|
+
? getDocumentNode({ ruleId, context, schema, node: node.rawNode() })
|
438
|
+
: node.rawNode();
|
439
|
+
validateDocument(node, context, schema, documentNode, ruleFn);
|
446
440
|
},
|
447
441
|
};
|
448
442
|
},
|
@@ -452,21 +446,27 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
|
|
452
446
|
const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-definitions', 'ExecutableDefinitions', {
|
453
447
|
category: 'Operations',
|
454
448
|
description: `A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.`,
|
449
|
+
requiresSchema: true,
|
455
450
|
}), validationToRule('fields-on-correct-type', 'FieldsOnCorrectType', {
|
456
451
|
category: 'Operations',
|
457
452
|
description: 'A GraphQL document is only valid if all fields selected are defined by the parent type, or are an allowed meta field such as `__typename`.',
|
453
|
+
requiresSchema: true,
|
458
454
|
}), validationToRule('fragments-on-composite-type', 'FragmentsOnCompositeTypes', {
|
459
455
|
category: 'Operations',
|
460
456
|
description: `Fragments use a type condition to determine if they apply, since fragments can only be spread into a composite type (object, interface, or union), the type condition must also be a composite type.`,
|
457
|
+
requiresSchema: true,
|
461
458
|
}), validationToRule('known-argument-names', 'KnownArgumentNames', {
|
462
459
|
category: ['Schema', 'Operations'],
|
463
460
|
description: `A GraphQL field is only valid if all supplied arguments are defined by that field.`,
|
461
|
+
requiresSchema: true,
|
464
462
|
}), validationToRule('known-directives', 'KnownDirectives', {
|
465
463
|
category: ['Schema', 'Operations'],
|
466
464
|
description: `A GraphQL document is only valid if all \`@directives\` are known by the schema and legally positioned.`,
|
465
|
+
requiresSchema: true,
|
467
466
|
}), validationToRule('known-fragment-names', 'KnownFragmentNames', {
|
468
467
|
category: 'Operations',
|
469
468
|
description: `A GraphQL document is only valid if all \`...Fragment\` fragment spreads refer to fragments defined in the same document.`,
|
469
|
+
requiresSchema: true,
|
470
470
|
requiresSiblings: true,
|
471
471
|
examples: [
|
472
472
|
{
|
@@ -517,27 +517,31 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
517
517
|
}, handleMissingFragments), validationToRule('known-type-names', 'KnownTypeNames', {
|
518
518
|
category: ['Schema', 'Operations'],
|
519
519
|
description: `A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.`,
|
520
|
+
requiresSchema: true,
|
520
521
|
}), validationToRule('lone-anonymous-operation', 'LoneAnonymousOperation', {
|
521
522
|
category: 'Operations',
|
522
523
|
description: `A GraphQL document is only valid if when it contains an anonymous operation (the query short-hand) that it contains only that one operation definition.`,
|
524
|
+
requiresSchema: true,
|
523
525
|
}), validationToRule('lone-schema-definition', 'LoneSchemaDefinition', {
|
524
526
|
category: 'Schema',
|
525
527
|
description: `A GraphQL document is only valid if it contains only one schema definition.`,
|
526
|
-
requiresSchema: false,
|
527
528
|
}), validationToRule('no-fragment-cycles', 'NoFragmentCycles', {
|
528
529
|
category: 'Operations',
|
529
530
|
description: `A GraphQL fragment is only valid when it does not have cycles in fragments usage.`,
|
531
|
+
requiresSchema: true,
|
530
532
|
}), validationToRule('no-undefined-variables', 'NoUndefinedVariables', {
|
531
533
|
category: 'Operations',
|
532
534
|
description: `A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.`,
|
535
|
+
requiresSchema: true,
|
533
536
|
requiresSiblings: true,
|
534
537
|
}, handleMissingFragments), validationToRule('no-unused-fragments', 'NoUnusedFragments', {
|
535
538
|
category: 'Operations',
|
536
539
|
description: `A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.`,
|
540
|
+
requiresSchema: true,
|
537
541
|
requiresSiblings: true,
|
538
|
-
}, ({
|
542
|
+
}, ({ ruleId, context, schema, node }) => {
|
539
543
|
const siblings = requireSiblingsOperations(ruleId, context);
|
540
|
-
const
|
544
|
+
const FilePathToDocumentsMap = [...siblings.getOperations(), ...siblings.getFragments()].reduce((map, { filePath, document }) => {
|
541
545
|
var _a;
|
542
546
|
(_a = map[filePath]) !== null && _a !== void 0 ? _a : (map[filePath] = []);
|
543
547
|
map[filePath].push(document);
|
@@ -549,8 +553,8 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
549
553
|
return node;
|
550
554
|
}
|
551
555
|
// skip iteration over documents for current filepath
|
552
|
-
delete
|
553
|
-
for (const [filePath, documents] of Object.entries(
|
556
|
+
delete FilePathToDocumentsMap[currentFilePath];
|
557
|
+
for (const [filePath, documents] of Object.entries(FilePathToDocumentsMap)) {
|
554
558
|
const missingFragments = getMissingFragments(schema, {
|
555
559
|
kind: Kind.DOCUMENT,
|
556
560
|
definitions: documents,
|
@@ -569,70 +573,75 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
569
573
|
}), validationToRule('no-unused-variables', 'NoUnusedVariables', {
|
570
574
|
category: 'Operations',
|
571
575
|
description: `A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.`,
|
576
|
+
requiresSchema: true,
|
572
577
|
requiresSiblings: true,
|
573
578
|
}, handleMissingFragments), validationToRule('overlapping-fields-can-be-merged', 'OverlappingFieldsCanBeMerged', {
|
574
579
|
category: 'Operations',
|
575
580
|
description: `A selection set is only valid if all fields (including spreading any fragments) either correspond to distinct response names or can be merged without ambiguity.`,
|
581
|
+
requiresSchema: true,
|
576
582
|
}), validationToRule('possible-fragment-spread', 'PossibleFragmentSpreads', {
|
577
583
|
category: 'Operations',
|
578
584
|
description: `A fragment spread is only valid if the type condition could ever possibly be true: if there is a non-empty intersection of the possible parent types, and possible types which pass the type condition.`,
|
585
|
+
requiresSchema: true,
|
579
586
|
}), validationToRule('possible-type-extension', 'PossibleTypeExtensions', {
|
580
587
|
category: 'Schema',
|
581
588
|
description: `A type extension is only valid if the type is defined and has the same kind.`,
|
582
|
-
requiresSchema: false,
|
583
589
|
recommended: false, // TODO: enable after https://github.com/dotansimha/graphql-eslint/issues/787 will be fixed
|
584
590
|
}), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
|
585
591
|
category: ['Schema', 'Operations'],
|
586
592
|
description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
|
593
|
+
requiresSchema: true,
|
587
594
|
}), validationToRule('scalar-leafs', 'ScalarLeafs', {
|
588
595
|
category: 'Operations',
|
589
596
|
description: `A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.`,
|
597
|
+
requiresSchema: true,
|
590
598
|
}), validationToRule('one-field-subscriptions', 'SingleFieldSubscriptions', {
|
591
599
|
category: 'Operations',
|
592
600
|
description: `A GraphQL subscription is valid only if it contains a single root field.`,
|
601
|
+
requiresSchema: true,
|
593
602
|
}), validationToRule('unique-argument-names', 'UniqueArgumentNames', {
|
594
603
|
category: 'Operations',
|
595
604
|
description: `A GraphQL field or directive is only valid if all supplied arguments are uniquely named.`,
|
605
|
+
requiresSchema: true,
|
596
606
|
}), validationToRule('unique-directive-names', 'UniqueDirectiveNames', {
|
597
607
|
category: 'Schema',
|
598
608
|
description: `A GraphQL document is only valid if all defined directives have unique names.`,
|
599
|
-
requiresSchema: false,
|
600
609
|
}), validationToRule('unique-directive-names-per-location', 'UniqueDirectivesPerLocation', {
|
601
610
|
category: ['Schema', 'Operations'],
|
602
611
|
description: `A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.`,
|
612
|
+
requiresSchema: true,
|
603
613
|
}), validationToRule('unique-enum-value-names', 'UniqueEnumValueNames', {
|
604
614
|
category: 'Schema',
|
605
615
|
description: `A GraphQL enum type is only valid if all its values are uniquely named.`,
|
606
|
-
requiresSchema: false,
|
607
616
|
recommended: false,
|
608
617
|
}), validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
|
609
618
|
category: 'Schema',
|
610
619
|
description: `A GraphQL complex type is only valid if all its fields are uniquely named.`,
|
611
|
-
requiresSchema: false,
|
612
620
|
}), validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
|
613
621
|
category: 'Operations',
|
614
622
|
description: `A GraphQL input object value is only valid if all supplied fields are uniquely named.`,
|
615
|
-
requiresSchema: false,
|
616
623
|
}), validationToRule('unique-operation-types', 'UniqueOperationTypes', {
|
617
624
|
category: 'Schema',
|
618
625
|
description: `A GraphQL document is only valid if it has only one type per operation.`,
|
619
|
-
requiresSchema: false,
|
620
626
|
}), validationToRule('unique-type-names', 'UniqueTypeNames', {
|
621
627
|
category: 'Schema',
|
622
628
|
description: `A GraphQL document is only valid if all defined types have unique names.`,
|
623
|
-
requiresSchema: false,
|
624
629
|
}), validationToRule('unique-variable-names', 'UniqueVariableNames', {
|
625
630
|
category: 'Operations',
|
626
631
|
description: `A GraphQL operation is only valid if all its variables are uniquely named.`,
|
632
|
+
requiresSchema: true,
|
627
633
|
}), validationToRule('value-literals-of-correct-type', 'ValuesOfCorrectType', {
|
628
634
|
category: 'Operations',
|
629
635
|
description: `A GraphQL document is only valid if all value literals are of the type expected at their position.`,
|
636
|
+
requiresSchema: true,
|
630
637
|
}), validationToRule('variables-are-input-types', 'VariablesAreInputTypes', {
|
631
638
|
category: 'Operations',
|
632
639
|
description: `A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).`,
|
640
|
+
requiresSchema: true,
|
633
641
|
}), validationToRule('variables-in-allowed-position', 'VariablesInAllowedPosition', {
|
634
642
|
category: 'Operations',
|
635
643
|
description: `Variables passed to field arguments conform to type.`,
|
644
|
+
requiresSchema: true,
|
636
645
|
}));
|
637
646
|
|
638
647
|
const ALPHABETIZE = 'ALPHABETIZE';
|
package/package.json
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@graphql-eslint/eslint-plugin",
|
3
|
-
"version": "3.2.0-alpha-
|
3
|
+
"version": "3.2.0-alpha-6aa2721.0",
|
4
|
+
"description": "GraphQL plugin for ESLint",
|
4
5
|
"sideEffects": false,
|
5
6
|
"peerDependencies": {
|
6
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"
|
@@ -15,6 +16,12 @@
|
|
15
16
|
"lodash.lowercase": "4.3.0"
|
16
17
|
},
|
17
18
|
"repository": "https://github.com/dotansimha/graphql-eslint",
|
19
|
+
"keywords": [
|
20
|
+
"eslint",
|
21
|
+
"eslintplugin",
|
22
|
+
"eslint-plugin",
|
23
|
+
"graphql"
|
24
|
+
],
|
18
25
|
"author": "Dotan Simha <dotansimha@gmail.com>",
|
19
26
|
"license": "MIT",
|
20
27
|
"main": "index.js",
|
package/types.d.ts
CHANGED
@@ -49,8 +49,8 @@ export declare type CategoryType = 'Schema' | 'Operations';
|
|
49
49
|
export declare type RuleDocsInfo<T> = {
|
50
50
|
docs: Omit<Rule.RuleMetaData['docs'], 'category'> & {
|
51
51
|
category: CategoryType | CategoryType[];
|
52
|
-
requiresSchema?:
|
53
|
-
requiresSiblings?:
|
52
|
+
requiresSchema?: true;
|
53
|
+
requiresSiblings?: true;
|
54
54
|
examples?: {
|
55
55
|
title: string;
|
56
56
|
code: string;
|