@graphql-eslint/eslint-plugin 3.13.1 → 3.14.0-alpha-20221220000306-eefc8db
Sign up to get free protection for your applications and to get access to all the features.
- package/documents.d.ts +3 -3
- package/estree-converter/types.d.ts +8 -8
- package/estree-converter/utils.d.ts +1 -1
- package/index.js +215 -91
- package/index.mjs +215 -91
- package/package.json +1 -1
- package/processor.d.ts +1 -1
- package/rules/alphabetize.d.ts +1 -1
- package/rules/description-style.d.ts +1 -1
- package/rules/graphql-js-validation.d.ts +1 -1
- package/rules/input-name.d.ts +1 -1
- package/rules/match-document-filename.d.ts +3 -3
- package/rules/naming-convention.d.ts +5 -5
- package/rules/no-root-type.d.ts +1 -1
- package/rules/relay-arguments.d.ts +1 -1
- package/rules/relay-edge-types.d.ts +1 -1
- package/rules/require-description.d.ts +2 -2
- package/rules/require-id-when-available.d.ts +1 -1
- package/rules/selection-set-depth.d.ts +1 -1
- package/rules/strict-id-in-types.d.ts +1 -1
- package/testkit.d.ts +3 -3
- package/types.d.ts +15 -15
- package/utils.d.ts +1 -1
- package/README.md +0 -266
- package/docs/README.md +0 -76
- package/docs/custom-rules.md +0 -148
- package/docs/deprecated-rules.md +0 -21
- package/docs/parser-options.md +0 -85
- package/docs/parser.md +0 -49
- package/docs/rules/alphabetize.md +0 -178
- package/docs/rules/description-style.md +0 -54
- package/docs/rules/executable-definitions.md +0 -17
- package/docs/rules/fields-on-correct-type.md +0 -17
- package/docs/rules/fragments-on-composite-type.md +0 -17
- package/docs/rules/input-name.md +0 -76
- package/docs/rules/known-argument-names.md +0 -17
- package/docs/rules/known-directives.md +0 -44
- package/docs/rules/known-fragment-names.md +0 -69
- package/docs/rules/known-type-names.md +0 -17
- package/docs/rules/lone-anonymous-operation.md +0 -17
- package/docs/rules/lone-schema-definition.md +0 -17
- package/docs/rules/match-document-filename.md +0 -156
- package/docs/rules/naming-convention.md +0 -300
- package/docs/rules/no-anonymous-operations.md +0 -39
- package/docs/rules/no-case-insensitive-enum-values-duplicates.md +0 -43
- package/docs/rules/no-deprecated.md +0 -85
- package/docs/rules/no-duplicate-fields.md +0 -65
- package/docs/rules/no-fragment-cycles.md +0 -17
- package/docs/rules/no-hashtag-description.md +0 -59
- package/docs/rules/no-root-type.md +0 -53
- package/docs/rules/no-scalar-result-type-on-mutation.md +0 -37
- package/docs/rules/no-typename-prefix.md +0 -39
- package/docs/rules/no-undefined-variables.md +0 -17
- package/docs/rules/no-unreachable-types.md +0 -49
- package/docs/rules/no-unused-fields.md +0 -62
- package/docs/rules/no-unused-fragments.md +0 -17
- package/docs/rules/no-unused-variables.md +0 -17
- package/docs/rules/one-field-subscriptions.md +0 -17
- package/docs/rules/overlapping-fields-can-be-merged.md +0 -17
- package/docs/rules/possible-fragment-spread.md +0 -17
- package/docs/rules/possible-type-extension.md +0 -15
- package/docs/rules/provided-required-arguments.md +0 -17
- package/docs/rules/relay-arguments.md +0 -57
- package/docs/rules/relay-connection-types.md +0 -42
- package/docs/rules/relay-edge-types.md +0 -56
- package/docs/rules/relay-page-info.md +0 -32
- package/docs/rules/require-deprecation-date.md +0 -57
- package/docs/rules/require-deprecation-reason.md +0 -47
- package/docs/rules/require-description.md +0 -115
- package/docs/rules/require-field-of-type-query-in-mutation-result.md +0 -47
- package/docs/rules/require-id-when-available.md +0 -88
- package/docs/rules/scalar-leafs.md +0 -17
- package/docs/rules/selection-set-depth.md +0 -76
- package/docs/rules/strict-id-in-types.md +0 -130
- package/docs/rules/unique-argument-names.md +0 -17
- package/docs/rules/unique-directive-names-per-location.md +0 -17
- package/docs/rules/unique-directive-names.md +0 -17
- package/docs/rules/unique-enum-value-names.md +0 -15
- package/docs/rules/unique-field-definition-names.md +0 -17
- package/docs/rules/unique-fragment-name.md +0 -51
- package/docs/rules/unique-input-field-names.md +0 -17
- package/docs/rules/unique-operation-name.md +0 -55
- package/docs/rules/unique-operation-types.md +0 -17
- package/docs/rules/unique-type-names.md +0 -17
- package/docs/rules/unique-variable-names.md +0 -17
- package/docs/rules/value-literals-of-correct-type.md +0 -17
- package/docs/rules/variables-are-input-types.md +0 -17
- package/docs/rules/variables-in-allowed-position.md +0 -17
package/index.mjs
CHANGED
@@ -215,7 +215,8 @@ const ARRAY_DEFAULT_OPTIONS = {
|
|
215
215
|
};
|
216
216
|
const englishJoinWords = words => new Intl.ListFormat('en-US', { type: 'disjunction' }).format(words);
|
217
217
|
|
218
|
-
function validateDocument(context, schema = null, documentNode, rule) {
|
218
|
+
function validateDocument({ context, schema = null, documentNode, rule, hasDidYouMeanSuggestions, }) {
|
219
|
+
var _a;
|
219
220
|
if (documentNode.definitions.length === 0) {
|
220
221
|
return;
|
221
222
|
}
|
@@ -239,9 +240,20 @@ function validateDocument(context, schema = null, documentNode, rule) {
|
|
239
240
|
? sourceCode.getNodeByRangeIndex(token.range[1] + 1).loc
|
240
241
|
: token.loc;
|
241
242
|
}
|
243
|
+
const didYouMeanContent = (_a = error.message.match(/Did you mean (?<content>.*)\?$/)) === null || _a === void 0 ? void 0 : _a.groups.content;
|
244
|
+
const matches = didYouMeanContent ? [...didYouMeanContent.matchAll(/"(?<name>[^"]*)"/g)] : [];
|
242
245
|
context.report({
|
243
246
|
loc,
|
244
247
|
message: error.message,
|
248
|
+
suggest: hasDidYouMeanSuggestions
|
249
|
+
? matches.map(match => {
|
250
|
+
const { name } = match.groups;
|
251
|
+
return {
|
252
|
+
desc: `Rename to \`${name}\``,
|
253
|
+
fix: fixer => fixer.replaceText(token, name),
|
254
|
+
};
|
255
|
+
})
|
256
|
+
: [],
|
245
257
|
});
|
246
258
|
}
|
247
259
|
}
|
@@ -295,7 +307,7 @@ const handleMissingFragments = ({ ruleId, context, node }) => {
|
|
295
307
|
}
|
296
308
|
return node;
|
297
309
|
};
|
298
|
-
const validationToRule = (ruleId, ruleName,
|
310
|
+
const validationToRule = ({ ruleId, ruleName, getDocumentNode, schema = [], hasDidYouMeanSuggestions, }, docs) => {
|
299
311
|
let ruleFn = null;
|
300
312
|
try {
|
301
313
|
ruleFn = require(`graphql/validation/rules/${ruleName}Rule`)[`${ruleName}Rule`];
|
@@ -319,6 +331,7 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode, schema = [])
|
|
319
331
|
description: `${docs.description}\n\n> This rule is a wrapper around a \`graphql-js\` validation function.`,
|
320
332
|
},
|
321
333
|
schema,
|
334
|
+
hasSuggestions: hasDidYouMeanSuggestions,
|
322
335
|
},
|
323
336
|
create(context) {
|
324
337
|
if (!ruleFn) {
|
@@ -333,30 +346,79 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode, schema = [])
|
|
333
346
|
const documentNode = getDocumentNode
|
334
347
|
? getDocumentNode({ ruleId, context, node: node.rawNode() })
|
335
348
|
: node.rawNode();
|
336
|
-
validateDocument(
|
349
|
+
validateDocument({
|
350
|
+
context,
|
351
|
+
schema,
|
352
|
+
documentNode,
|
353
|
+
rule: ruleFn,
|
354
|
+
hasDidYouMeanSuggestions,
|
355
|
+
});
|
337
356
|
},
|
338
357
|
};
|
339
358
|
},
|
340
359
|
},
|
341
360
|
};
|
342
361
|
};
|
343
|
-
const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule(
|
362
|
+
const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule({
|
363
|
+
ruleId: 'executable-definitions',
|
364
|
+
ruleName: 'ExecutableDefinitions',
|
365
|
+
}, {
|
344
366
|
category: 'Operations',
|
345
367
|
description: 'A GraphQL document is only valid for execution if all definitions are either operation or fragment definitions.',
|
346
368
|
requiresSchema: true,
|
347
|
-
}), validationToRule(
|
369
|
+
}), validationToRule({
|
370
|
+
ruleId: 'fields-on-correct-type',
|
371
|
+
ruleName: 'FieldsOnCorrectType',
|
372
|
+
hasDidYouMeanSuggestions: true,
|
373
|
+
}, {
|
348
374
|
category: 'Operations',
|
349
375
|
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`.',
|
350
376
|
requiresSchema: true,
|
351
|
-
}), validationToRule(
|
377
|
+
}), validationToRule({
|
378
|
+
ruleId: 'fragments-on-composite-type',
|
379
|
+
ruleName: 'FragmentsOnCompositeTypes',
|
380
|
+
}, {
|
352
381
|
category: 'Operations',
|
353
382
|
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.',
|
354
383
|
requiresSchema: true,
|
355
|
-
}), validationToRule(
|
384
|
+
}), validationToRule({
|
385
|
+
ruleId: 'known-argument-names',
|
386
|
+
ruleName: 'KnownArgumentNames',
|
387
|
+
hasDidYouMeanSuggestions: true,
|
388
|
+
}, {
|
356
389
|
category: ['Schema', 'Operations'],
|
357
390
|
description: 'A GraphQL field is only valid if all supplied arguments are defined by that field.',
|
358
391
|
requiresSchema: true,
|
359
|
-
}), validationToRule(
|
392
|
+
}), validationToRule({
|
393
|
+
ruleId: 'known-directives',
|
394
|
+
ruleName: 'KnownDirectives',
|
395
|
+
getDocumentNode({ context, node: documentNode }) {
|
396
|
+
const { ignoreClientDirectives = [] } = context.options[0] || {};
|
397
|
+
if (ignoreClientDirectives.length === 0) {
|
398
|
+
return documentNode;
|
399
|
+
}
|
400
|
+
const filterDirectives = (node) => ({
|
401
|
+
...node,
|
402
|
+
directives: node.directives.filter(directive => !ignoreClientDirectives.includes(directive.name.value)),
|
403
|
+
});
|
404
|
+
return visit(documentNode, {
|
405
|
+
Field: filterDirectives,
|
406
|
+
OperationDefinition: filterDirectives,
|
407
|
+
});
|
408
|
+
},
|
409
|
+
schema: {
|
410
|
+
type: 'array',
|
411
|
+
maxItems: 1,
|
412
|
+
items: {
|
413
|
+
type: 'object',
|
414
|
+
additionalProperties: false,
|
415
|
+
required: ['ignoreClientDirectives'],
|
416
|
+
properties: {
|
417
|
+
ignoreClientDirectives: ARRAY_DEFAULT_OPTIONS,
|
418
|
+
},
|
419
|
+
},
|
420
|
+
},
|
421
|
+
}, {
|
360
422
|
category: ['Schema', 'Operations'],
|
361
423
|
description: 'A GraphQL document is only valid if all `@directive`s are known by the schema and legally positioned.',
|
362
424
|
requiresSchema: true,
|
@@ -373,31 +435,11 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
373
435
|
`,
|
374
436
|
},
|
375
437
|
],
|
376
|
-
}, ({
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
}
|
381
|
-
const filterDirectives = (node) => ({
|
382
|
-
...node,
|
383
|
-
directives: node.directives.filter(directive => !ignoreClientDirectives.includes(directive.name.value)),
|
384
|
-
});
|
385
|
-
return visit(documentNode, {
|
386
|
-
Field: filterDirectives,
|
387
|
-
OperationDefinition: filterDirectives,
|
388
|
-
});
|
438
|
+
}), validationToRule({
|
439
|
+
ruleId: 'known-fragment-names',
|
440
|
+
ruleName: 'KnownFragmentNames',
|
441
|
+
getDocumentNode: handleMissingFragments,
|
389
442
|
}, {
|
390
|
-
type: 'array',
|
391
|
-
maxItems: 1,
|
392
|
-
items: {
|
393
|
-
type: 'object',
|
394
|
-
additionalProperties: false,
|
395
|
-
required: ['ignoreClientDirectives'],
|
396
|
-
properties: {
|
397
|
-
ignoreClientDirectives: ARRAY_DEFAULT_OPTIONS,
|
398
|
-
},
|
399
|
-
},
|
400
|
-
}), validationToRule('known-fragment-names', 'KnownFragmentNames', {
|
401
443
|
category: 'Operations',
|
402
444
|
description: 'A GraphQL document is only valid if all `...Fragment` fragment spreads refer to fragments defined in the same document.',
|
403
445
|
requiresSchema: true,
|
@@ -448,138 +490,220 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
|
|
448
490
|
`,
|
449
491
|
},
|
450
492
|
],
|
451
|
-
}
|
493
|
+
}), validationToRule({
|
494
|
+
ruleId: 'known-type-names',
|
495
|
+
ruleName: 'KnownTypeNames',
|
496
|
+
hasDidYouMeanSuggestions: true,
|
497
|
+
}, {
|
452
498
|
category: ['Schema', 'Operations'],
|
453
499
|
description: 'A GraphQL document is only valid if referenced types (specifically variable definitions and fragment conditions) are defined by the type schema.',
|
454
500
|
requiresSchema: true,
|
455
|
-
}), validationToRule(
|
501
|
+
}), validationToRule({
|
502
|
+
ruleId: 'lone-anonymous-operation',
|
503
|
+
ruleName: 'LoneAnonymousOperation',
|
504
|
+
}, {
|
456
505
|
category: 'Operations',
|
457
506
|
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.',
|
458
507
|
requiresSchema: true,
|
459
|
-
}), validationToRule(
|
508
|
+
}), validationToRule({
|
509
|
+
ruleId: 'lone-schema-definition',
|
510
|
+
ruleName: 'LoneSchemaDefinition',
|
511
|
+
}, {
|
460
512
|
category: 'Schema',
|
461
513
|
description: 'A GraphQL document is only valid if it contains only one schema definition.',
|
462
|
-
}), validationToRule(
|
514
|
+
}), validationToRule({
|
515
|
+
ruleId: 'no-fragment-cycles',
|
516
|
+
ruleName: 'NoFragmentCycles',
|
517
|
+
}, {
|
463
518
|
category: 'Operations',
|
464
519
|
description: 'A GraphQL fragment is only valid when it does not have cycles in fragments usage.',
|
465
520
|
requiresSchema: true,
|
466
|
-
}), validationToRule(
|
521
|
+
}), validationToRule({
|
522
|
+
ruleId: 'no-undefined-variables',
|
523
|
+
ruleName: 'NoUndefinedVariables',
|
524
|
+
getDocumentNode: handleMissingFragments,
|
525
|
+
}, {
|
467
526
|
category: 'Operations',
|
468
527
|
description: 'A GraphQL operation is only valid if all variables encountered, both directly and via fragment spreads, are defined by that operation.',
|
469
528
|
requiresSchema: true,
|
470
529
|
requiresSiblings: true,
|
471
|
-
}
|
530
|
+
}), validationToRule({
|
531
|
+
ruleId: 'no-unused-fragments',
|
532
|
+
ruleName: 'NoUnusedFragments',
|
533
|
+
getDocumentNode: ({ ruleId, context, node }) => {
|
534
|
+
const siblings = requireSiblingsOperations(ruleId, context);
|
535
|
+
const FilePathToDocumentsMap = [
|
536
|
+
...siblings.getOperations(),
|
537
|
+
...siblings.getFragments(),
|
538
|
+
].reduce((map, { filePath, document }) => {
|
539
|
+
var _a;
|
540
|
+
(_a = map[filePath]) !== null && _a !== void 0 ? _a : (map[filePath] = []);
|
541
|
+
map[filePath].push(document);
|
542
|
+
return map;
|
543
|
+
}, Object.create(null));
|
544
|
+
const getParentNode = (currentFilePath, node) => {
|
545
|
+
const { fragmentDefs } = getFragmentDefsAndFragmentSpreads(node);
|
546
|
+
if (fragmentDefs.size === 0) {
|
547
|
+
return node;
|
548
|
+
}
|
549
|
+
// skip iteration over documents for current filepath
|
550
|
+
delete FilePathToDocumentsMap[currentFilePath];
|
551
|
+
for (const [filePath, documents] of Object.entries(FilePathToDocumentsMap)) {
|
552
|
+
const missingFragments = getMissingFragments({
|
553
|
+
kind: Kind.DOCUMENT,
|
554
|
+
definitions: documents,
|
555
|
+
});
|
556
|
+
const isCurrentFileImportFragment = missingFragments.some(fragment => fragmentDefs.has(fragment));
|
557
|
+
if (isCurrentFileImportFragment) {
|
558
|
+
return getParentNode(filePath, {
|
559
|
+
kind: Kind.DOCUMENT,
|
560
|
+
definitions: [...node.definitions, ...documents],
|
561
|
+
});
|
562
|
+
}
|
563
|
+
}
|
564
|
+
return node;
|
565
|
+
};
|
566
|
+
return getParentNode(context.getFilename(), node);
|
567
|
+
},
|
568
|
+
}, {
|
472
569
|
category: 'Operations',
|
473
570
|
description: 'A GraphQL document is only valid if all fragment definitions are spread within operations, or spread within other fragments spread within operations.',
|
474
571
|
requiresSchema: true,
|
475
572
|
requiresSiblings: true,
|
476
|
-
}, ({
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
].reduce((map, { filePath, document }) => {
|
482
|
-
var _a;
|
483
|
-
(_a = map[filePath]) !== null && _a !== void 0 ? _a : (map[filePath] = []);
|
484
|
-
map[filePath].push(document);
|
485
|
-
return map;
|
486
|
-
}, Object.create(null));
|
487
|
-
const getParentNode = (currentFilePath, node) => {
|
488
|
-
const { fragmentDefs } = getFragmentDefsAndFragmentSpreads(node);
|
489
|
-
if (fragmentDefs.size === 0) {
|
490
|
-
return node;
|
491
|
-
}
|
492
|
-
// skip iteration over documents for current filepath
|
493
|
-
delete FilePathToDocumentsMap[currentFilePath];
|
494
|
-
for (const [filePath, documents] of Object.entries(FilePathToDocumentsMap)) {
|
495
|
-
const missingFragments = getMissingFragments({
|
496
|
-
kind: Kind.DOCUMENT,
|
497
|
-
definitions: documents,
|
498
|
-
});
|
499
|
-
const isCurrentFileImportFragment = missingFragments.some(fragment => fragmentDefs.has(fragment));
|
500
|
-
if (isCurrentFileImportFragment) {
|
501
|
-
return getParentNode(filePath, {
|
502
|
-
kind: Kind.DOCUMENT,
|
503
|
-
definitions: [...node.definitions, ...documents],
|
504
|
-
});
|
505
|
-
}
|
506
|
-
}
|
507
|
-
return node;
|
508
|
-
};
|
509
|
-
return getParentNode(context.getFilename(), node);
|
510
|
-
}), validationToRule('no-unused-variables', 'NoUnusedVariables', {
|
573
|
+
}), validationToRule({
|
574
|
+
ruleId: 'no-unused-variables',
|
575
|
+
ruleName: 'NoUnusedVariables',
|
576
|
+
getDocumentNode: handleMissingFragments,
|
577
|
+
}, {
|
511
578
|
category: 'Operations',
|
512
579
|
description: 'A GraphQL operation is only valid if all variables defined by an operation are used, either directly or within a spread fragment.',
|
513
580
|
requiresSchema: true,
|
514
581
|
requiresSiblings: true,
|
515
|
-
}
|
582
|
+
}), validationToRule({
|
583
|
+
ruleId: 'overlapping-fields-can-be-merged',
|
584
|
+
ruleName: 'OverlappingFieldsCanBeMerged',
|
585
|
+
}, {
|
516
586
|
category: 'Operations',
|
517
587
|
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.',
|
518
588
|
requiresSchema: true,
|
519
|
-
}), validationToRule(
|
589
|
+
}), validationToRule({
|
590
|
+
ruleId: 'possible-fragment-spread',
|
591
|
+
ruleName: 'PossibleFragmentSpreads',
|
592
|
+
}, {
|
520
593
|
category: 'Operations',
|
521
594
|
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.',
|
522
595
|
requiresSchema: true,
|
523
|
-
}), validationToRule(
|
596
|
+
}), validationToRule({
|
597
|
+
ruleId: 'possible-type-extension',
|
598
|
+
ruleName: 'PossibleTypeExtensions',
|
599
|
+
hasDidYouMeanSuggestions: true,
|
600
|
+
}, {
|
524
601
|
category: 'Schema',
|
525
602
|
description: 'A type extension is only valid if the type is defined and has the same kind.',
|
526
603
|
// TODO: add in graphql-eslint v4
|
527
604
|
recommended: false,
|
528
605
|
requiresSchema: true,
|
529
606
|
isDisabledForAllConfig: true,
|
530
|
-
}), validationToRule(
|
607
|
+
}), validationToRule({
|
608
|
+
ruleId: 'provided-required-arguments',
|
609
|
+
ruleName: 'ProvidedRequiredArguments',
|
610
|
+
}, {
|
531
611
|
category: ['Schema', 'Operations'],
|
532
612
|
description: 'A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.',
|
533
613
|
requiresSchema: true,
|
534
|
-
}), validationToRule(
|
614
|
+
}), validationToRule({
|
615
|
+
ruleId: 'scalar-leafs',
|
616
|
+
ruleName: 'ScalarLeafs',
|
617
|
+
hasDidYouMeanSuggestions: true,
|
618
|
+
}, {
|
535
619
|
category: 'Operations',
|
536
620
|
description: 'A GraphQL document is valid only if all leaf fields (fields without sub selections) are of scalar or enum types.',
|
537
621
|
requiresSchema: true,
|
538
|
-
}), validationToRule(
|
622
|
+
}), validationToRule({
|
623
|
+
ruleId: 'one-field-subscriptions',
|
624
|
+
ruleName: 'SingleFieldSubscriptions',
|
625
|
+
}, {
|
539
626
|
category: 'Operations',
|
540
627
|
description: 'A GraphQL subscription is valid only if it contains a single root field.',
|
541
628
|
requiresSchema: true,
|
542
|
-
}), validationToRule(
|
629
|
+
}), validationToRule({
|
630
|
+
ruleId: 'unique-argument-names',
|
631
|
+
ruleName: 'UniqueArgumentNames',
|
632
|
+
}, {
|
543
633
|
category: 'Operations',
|
544
634
|
description: 'A GraphQL field or directive is only valid if all supplied arguments are uniquely named.',
|
545
635
|
requiresSchema: true,
|
546
|
-
}), validationToRule(
|
636
|
+
}), validationToRule({
|
637
|
+
ruleId: 'unique-directive-names',
|
638
|
+
ruleName: 'UniqueDirectiveNames',
|
639
|
+
}, {
|
547
640
|
category: 'Schema',
|
548
641
|
description: 'A GraphQL document is only valid if all defined directives have unique names.',
|
549
|
-
}), validationToRule(
|
642
|
+
}), validationToRule({
|
643
|
+
ruleId: 'unique-directive-names-per-location',
|
644
|
+
ruleName: 'UniqueDirectivesPerLocation',
|
645
|
+
}, {
|
550
646
|
category: ['Schema', 'Operations'],
|
551
647
|
description: 'A GraphQL document is only valid if all non-repeatable directives at a given location are uniquely named.',
|
552
648
|
requiresSchema: true,
|
553
|
-
}), validationToRule(
|
649
|
+
}), validationToRule({
|
650
|
+
ruleId: 'unique-enum-value-names',
|
651
|
+
ruleName: 'UniqueEnumValueNames',
|
652
|
+
}, {
|
554
653
|
category: 'Schema',
|
555
654
|
description: 'A GraphQL enum type is only valid if all its values are uniquely named.',
|
556
655
|
recommended: false,
|
557
656
|
isDisabledForAllConfig: true,
|
558
|
-
}), validationToRule(
|
657
|
+
}), validationToRule({
|
658
|
+
ruleId: 'unique-field-definition-names',
|
659
|
+
ruleName: 'UniqueFieldDefinitionNames',
|
660
|
+
}, {
|
559
661
|
category: 'Schema',
|
560
662
|
description: 'A GraphQL complex type is only valid if all its fields are uniquely named.',
|
561
|
-
}), validationToRule(
|
663
|
+
}), validationToRule({
|
664
|
+
ruleId: 'unique-input-field-names',
|
665
|
+
ruleName: 'UniqueInputFieldNames',
|
666
|
+
}, {
|
562
667
|
category: 'Operations',
|
563
668
|
description: 'A GraphQL input object value is only valid if all supplied fields are uniquely named.',
|
564
|
-
}), validationToRule(
|
669
|
+
}), validationToRule({
|
670
|
+
ruleId: 'unique-operation-types',
|
671
|
+
ruleName: 'UniqueOperationTypes',
|
672
|
+
}, {
|
565
673
|
category: 'Schema',
|
566
674
|
description: 'A GraphQL document is only valid if it has only one type per operation.',
|
567
|
-
}), validationToRule(
|
675
|
+
}), validationToRule({
|
676
|
+
ruleId: 'unique-type-names',
|
677
|
+
ruleName: 'UniqueTypeNames',
|
678
|
+
}, {
|
568
679
|
category: 'Schema',
|
569
680
|
description: 'A GraphQL document is only valid if all defined types have unique names.',
|
570
|
-
}), validationToRule(
|
681
|
+
}), validationToRule({
|
682
|
+
ruleId: 'unique-variable-names',
|
683
|
+
ruleName: 'UniqueVariableNames',
|
684
|
+
}, {
|
571
685
|
category: 'Operations',
|
572
686
|
description: 'A GraphQL operation is only valid if all its variables are uniquely named.',
|
573
687
|
requiresSchema: true,
|
574
|
-
}), validationToRule(
|
688
|
+
}), validationToRule({
|
689
|
+
ruleId: 'value-literals-of-correct-type',
|
690
|
+
ruleName: 'ValuesOfCorrectType',
|
691
|
+
hasDidYouMeanSuggestions: true,
|
692
|
+
}, {
|
575
693
|
category: 'Operations',
|
576
694
|
description: 'A GraphQL document is only valid if all value literals are of the type expected at their position.',
|
577
695
|
requiresSchema: true,
|
578
|
-
}), validationToRule(
|
696
|
+
}), validationToRule({
|
697
|
+
ruleId: 'variables-are-input-types',
|
698
|
+
ruleName: 'VariablesAreInputTypes',
|
699
|
+
}, {
|
579
700
|
category: 'Operations',
|
580
701
|
description: 'A GraphQL operation is only valid if all the variables it defines are of input types (scalar, enum, or input object).',
|
581
702
|
requiresSchema: true,
|
582
|
-
}), validationToRule(
|
703
|
+
}), validationToRule({
|
704
|
+
ruleId: 'variables-in-allowed-position',
|
705
|
+
ruleName: 'VariablesInAllowedPosition',
|
706
|
+
}, {
|
583
707
|
category: 'Operations',
|
584
708
|
description: 'Variables passed to field arguments conform to type.',
|
585
709
|
requiresSchema: true,
|
package/package.json
CHANGED
package/processor.d.ts
CHANGED
package/rules/alphabetize.d.ts
CHANGED
@@ -4,7 +4,7 @@ declare const valuesEnum: ['EnumTypeDefinition'];
|
|
4
4
|
declare const selectionsEnum: ('OperationDefinition' | 'FragmentDefinition')[];
|
5
5
|
declare const variablesEnum: ['OperationDefinition'];
|
6
6
|
declare const argumentsEnum: ('FieldDefinition' | 'Field' | 'DirectiveDefinition' | 'Directive')[];
|
7
|
-
export
|
7
|
+
export type AlphabetizeConfig = {
|
8
8
|
fields?: typeof fieldsEnum;
|
9
9
|
values?: typeof valuesEnum;
|
10
10
|
selections?: typeof selectionsEnum;
|
@@ -1,2 +1,2 @@
|
|
1
|
-
import
|
1
|
+
import { GraphQLESLintRule } from '../types';
|
2
2
|
export declare const GRAPHQL_JS_VALIDATIONS: Record<string, GraphQLESLintRule>;
|
package/rules/input-name.d.ts
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
import { CaseStyle as _CaseStyle } from '../utils';
|
2
2
|
import { GraphQLESLintRule } from '../types';
|
3
|
-
|
3
|
+
type CaseStyle = _CaseStyle | 'matchDocumentStyle';
|
4
4
|
declare const ACCEPTED_EXTENSIONS: ['.gql', '.graphql'];
|
5
|
-
|
5
|
+
type PropertySchema = {
|
6
6
|
style?: CaseStyle;
|
7
7
|
suffix?: string;
|
8
8
|
};
|
9
|
-
export
|
9
|
+
export type MatchDocumentFilenameRuleConfig = {
|
10
10
|
fileExtension?: typeof ACCEPTED_EXTENSIONS[number];
|
11
11
|
query?: CaseStyle | PropertySchema;
|
12
12
|
mutation?: CaseStyle | PropertySchema;
|
@@ -15,9 +15,9 @@ declare const KindToDisplayName: {
|
|
15
15
|
FragmentDefinition: string;
|
16
16
|
VariableDefinition: string;
|
17
17
|
};
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
type AllowedKind = keyof typeof KindToDisplayName;
|
19
|
+
type AllowedStyle = 'camelCase' | 'PascalCase' | 'snake_case' | 'UPPER_CASE';
|
20
|
+
type PropertySchema = {
|
21
21
|
style?: AllowedStyle;
|
22
22
|
suffix?: string;
|
23
23
|
prefix?: string;
|
@@ -25,8 +25,8 @@ declare type PropertySchema = {
|
|
25
25
|
forbiddenSuffixes?: string[];
|
26
26
|
ignorePattern?: string;
|
27
27
|
};
|
28
|
-
|
29
|
-
export
|
28
|
+
type Options = AllowedStyle | PropertySchema;
|
29
|
+
export type NamingConventionRuleConfig = {
|
30
30
|
allowLeadingUnderscore?: boolean;
|
31
31
|
allowTrailingUnderscore?: boolean;
|
32
32
|
types?: Options;
|
package/rules/no-root-type.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import type { GraphQLESLintRule } from '../types';
|
2
2
|
declare const ROOT_TYPES: ('mutation' | 'subscription')[];
|
3
|
-
|
3
|
+
type NoRootTypeConfig = {
|
4
4
|
disallow: typeof ROOT_TYPES;
|
5
5
|
};
|
6
6
|
declare const rule: GraphQLESLintRule<[NoRootTypeConfig]>;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { Kind } from 'graphql';
|
2
2
|
import type { GraphQLESLintRule } from '../types';
|
3
3
|
declare const ALLOWED_KINDS: readonly [Kind.OBJECT_TYPE_DEFINITION, Kind.INTERFACE_TYPE_DEFINITION, Kind.ENUM_TYPE_DEFINITION, Kind.SCALAR_TYPE_DEFINITION, Kind.INPUT_OBJECT_TYPE_DEFINITION, Kind.UNION_TYPE_DEFINITION, Kind.DIRECTIVE_DEFINITION, Kind.FIELD_DEFINITION, Kind.INPUT_VALUE_DEFINITION, Kind.ENUM_VALUE_DEFINITION, Kind.OPERATION_DEFINITION];
|
4
|
-
|
5
|
-
export
|
4
|
+
type AllowedKind = typeof ALLOWED_KINDS[number];
|
5
|
+
export type RequireDescriptionRuleConfig = {
|
6
6
|
types?: boolean;
|
7
7
|
} & {
|
8
8
|
[key in AllowedKind]?: boolean;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { GraphQLESLintRule } from '../types';
|
2
|
-
export
|
2
|
+
export type RequireIdWhenAvailableRuleConfig = {
|
3
3
|
fieldName: string | string[];
|
4
4
|
};
|
5
5
|
declare const rule: GraphQLESLintRule<[RequireIdWhenAvailableRuleConfig], true>;
|
package/testkit.d.ts
CHANGED
@@ -2,14 +2,14 @@ import { RuleTester } from 'eslint';
|
|
2
2
|
import type { ASTKindToNode } from 'graphql';
|
3
3
|
import type { GraphQLESTreeNode } from './estree-converter';
|
4
4
|
import type { GraphQLESLintRule, ParserOptions } from './types';
|
5
|
-
export
|
5
|
+
export type GraphQLESLintRuleListener<WithTypeInfo extends boolean = false> = {
|
6
6
|
[K in keyof ASTKindToNode]?: (node: GraphQLESTreeNode<ASTKindToNode[K], WithTypeInfo>) => void;
|
7
7
|
} & Record<string, any>;
|
8
|
-
export
|
8
|
+
export type GraphQLValidTestCase<Options> = Omit<RuleTester.ValidTestCase, 'options' | 'parserOptions'> & {
|
9
9
|
options?: Options;
|
10
10
|
parserOptions?: ParserOptions;
|
11
11
|
};
|
12
|
-
export
|
12
|
+
export type GraphQLInvalidTestCase<T> = GraphQLValidTestCase<T> & {
|
13
13
|
errors: number | (RuleTester.TestCaseError | string)[];
|
14
14
|
output?: string | null;
|
15
15
|
};
|