@graphql-eslint/eslint-plugin 3.0.0-alpha-698204a.0 → 3.0.0-alpha-0a996de.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 CHANGED
@@ -38,21 +38,22 @@ const schemaRecommendedConfig = {
38
38
  'error',
39
39
  {
40
40
  types: 'PascalCase',
41
- fields: 'camelCase',
42
- overrides: {
43
- EnumValueDefinition: 'UPPER_CASE',
44
- 'FieldDefinition[parent.name.value=Query]': {
45
- forbiddenPrefixes: ['query', 'get'],
46
- forbiddenSuffixes: ['Query'],
47
- },
48
- 'FieldDefinition[parent.name.value=Mutation]': {
49
- forbiddenPrefixes: ['mutation'],
50
- forbiddenSuffixes: ['Mutation'],
51
- },
52
- 'FieldDefinition[parent.name.value=Subscription]': {
53
- forbiddenPrefixes: ['subscription'],
54
- forbiddenSuffixes: ['Subscription'],
55
- },
41
+ FieldDefinition: 'camelCase',
42
+ InputValueDefinition: 'camelCase',
43
+ Argument: 'camelCase',
44
+ DirectiveDefinition: 'camelCase',
45
+ EnumValueDefinition: 'UPPER_CASE',
46
+ 'FieldDefinition[parent.name.value=Query]': {
47
+ forbiddenPrefixes: ['query', 'get'],
48
+ forbiddenSuffixes: ['Query'],
49
+ },
50
+ 'FieldDefinition[parent.name.value=Mutation]': {
51
+ forbiddenPrefixes: ['mutation'],
52
+ forbiddenSuffixes: ['Mutation'],
53
+ },
54
+ 'FieldDefinition[parent.name.value=Subscription]': {
55
+ forbiddenPrefixes: ['subscription'],
56
+ forbiddenSuffixes: ['Subscription'],
56
57
  },
57
58
  },
58
59
  ],
@@ -60,9 +61,9 @@ const schemaRecommendedConfig = {
60
61
  '@graphql-eslint/no-hashtag-description': 'error',
61
62
  '@graphql-eslint/no-typename-prefix': 'error',
62
63
  '@graphql-eslint/no-unreachable-types': 'error',
63
- '@graphql-eslint/possible-type-extension': 'error',
64
64
  '@graphql-eslint/provided-required-arguments': 'error',
65
65
  '@graphql-eslint/require-deprecation-reason': 'error',
66
+ '@graphql-eslint/require-description': ['error', { types: true, DirectiveDefinition: true }],
66
67
  '@graphql-eslint/strict-id-in-types': 'error',
67
68
  '@graphql-eslint/unique-directive-names': 'error',
68
69
  '@graphql-eslint/unique-directive-names-per-location': 'error',
@@ -91,8 +92,8 @@ const schemaAllConfig = {
91
92
  '@graphql-eslint/no-root-type': 'off',
92
93
  '@graphql-eslint/no-scalar-result-type-on-mutation': 'error',
93
94
  '@graphql-eslint/no-unused-fields': 'off',
95
+ '@graphql-eslint/possible-type-extension': 'off',
94
96
  '@graphql-eslint/require-deprecation-date': 'error',
95
- '@graphql-eslint/require-description': ['error', { types: true, overrides: { DirectiveDefinition: true } }],
96
97
  '@graphql-eslint/require-field-of-type-query-in-mutation-result': 'error',
97
98
  },
98
99
  };
@@ -114,16 +115,13 @@ const operationsRecommendedConfig = {
114
115
  '@graphql-eslint/naming-convention': [
115
116
  'error',
116
117
  {
117
- overrides: {
118
- Argument: 'camelCase',
119
- VariableDefinition: 'camelCase',
120
- OperationDefinition: {
121
- style: 'PascalCase',
122
- forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
123
- forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
124
- },
125
- FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
118
+ VariableDefinition: 'camelCase',
119
+ OperationDefinition: {
120
+ style: 'PascalCase',
121
+ forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
122
+ forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
126
123
  },
124
+ FragmentDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Fragment'], forbiddenSuffixes: ['Fragment'] },
127
125
  },
128
126
  ],
129
127
  '@graphql-eslint/no-anonymous-operations': 'error',
@@ -389,9 +387,9 @@ const validationToRule = (name, ruleName, docs, getDocumentNode) => {
389
387
  [name]: {
390
388
  meta: {
391
389
  docs: {
390
+ recommended: true,
392
391
  ...docs,
393
392
  graphQLJSRuleName: ruleName,
394
- recommended: true,
395
393
  requiresSchema,
396
394
  url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${name}.md`,
397
395
  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).`,
@@ -567,6 +565,7 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
567
565
  category: 'Schema',
568
566
  description: `A type extension is only valid if the type is defined and has the same kind.`,
569
567
  requiresSchema: false,
568
+ recommended: false, // TODO: enable after https://github.com/dotansimha/graphql-eslint/issues/787 will be fixed
570
569
  }), validationToRule('provided-required-arguments', 'ProvidedRequiredArguments', {
571
570
  category: ['Schema', 'Operations'],
572
571
  description: `A field or directive is only valid if all required (non-null without a default value) field arguments have been provided.`,
@@ -912,23 +911,21 @@ const rule$1 = {
912
911
  properties: {
913
912
  style: {
914
913
  enum: ['block', 'inline'],
915
- default: 'inline',
914
+ default: 'block',
916
915
  },
917
916
  },
918
917
  },
919
918
  ],
920
919
  },
921
920
  create(context) {
922
- const { style } = context.options[0] || { style: 'inline' };
923
- const wrongDescriptionType = style === 'block' ? 'inline' : 'block';
921
+ const { style = 'block' } = context.options[0] || {};
922
+ const isBlock = style === 'block';
924
923
  return {
925
- '[description.type="StringValue"]': node => {
926
- if (node.description.block !== (style === 'block')) {
927
- context.report({
928
- loc: getLocation(node.description.loc),
929
- message: `Unexpected ${wrongDescriptionType} description`,
930
- });
931
- }
924
+ [`.description[type=StringValue][block!=${isBlock}]`](node) {
925
+ context.report({
926
+ loc: getLocation(node.loc),
927
+ message: `Unexpected ${isBlock ? 'inline' : 'block'} description`,
928
+ });
932
929
  },
933
930
  };
934
931
  },
@@ -1254,7 +1251,6 @@ const rule$3 = {
1254
1251
  },
1255
1252
  };
1256
1253
 
1257
- const FIELDS_KINDS = [graphql.Kind.FIELD_DEFINITION, graphql.Kind.INPUT_VALUE_DEFINITION, graphql.Kind.ARGUMENT, graphql.Kind.DIRECTIVE_DEFINITION];
1258
1254
  const KindToDisplayName = {
1259
1255
  // types
1260
1256
  [graphql.Kind.OBJECT_TYPE_DEFINITION]: 'Type',
@@ -1296,20 +1292,56 @@ const rule$4 = {
1296
1292
  examples: [
1297
1293
  {
1298
1294
  title: 'Incorrect',
1299
- usage: [{ types: 'PascalCase', fields: 'camelCase' }],
1295
+ usage: [{ types: 'PascalCase', FieldDefinition: 'camelCase' }],
1300
1296
  code: /* GraphQL */ `
1301
1297
  type user {
1302
1298
  first_name: String!
1303
1299
  }
1300
+ `,
1301
+ },
1302
+ {
1303
+ title: 'Incorrect',
1304
+ usage: [{ FragmentDefinition: { style: 'PascalCase', forbiddenSuffixes: ['Fragment'] } }],
1305
+ code: /* GraphQL */ `
1306
+ fragment UserFragment on User {
1307
+ # ...
1308
+ }
1309
+ `,
1310
+ },
1311
+ {
1312
+ title: 'Incorrect',
1313
+ usage: [{ 'FieldDefinition[parent.name.value=Query]': { forbiddenPrefixes: ['get'] } }],
1314
+ code: /* GraphQL */ `
1315
+ type Query {
1316
+ getUsers: [User!]!
1317
+ }
1304
1318
  `,
1305
1319
  },
1306
1320
  {
1307
1321
  title: 'Correct',
1308
- usage: [{ types: 'PascalCase', fields: 'camelCase' }],
1322
+ usage: [{ types: 'PascalCase', FieldDefinition: 'camelCase' }],
1309
1323
  code: /* GraphQL */ `
1310
1324
  type User {
1311
1325
  firstName: String
1312
1326
  }
1327
+ `,
1328
+ },
1329
+ {
1330
+ title: 'Correct',
1331
+ usage: [{ FragmentDefinition: { style: 'PascalCase', forbiddenSuffixes: ['Fragment'] } }],
1332
+ code: /* GraphQL */ `
1333
+ fragment UserFields on User {
1334
+ # ...
1335
+ }
1336
+ `,
1337
+ },
1338
+ {
1339
+ title: 'Correct',
1340
+ usage: [{ 'FieldDefinition[parent.name.value=Query]': { forbiddenPrefixes: ['get'] } }],
1341
+ code: /* GraphQL */ `
1342
+ type Query {
1343
+ users: [User!]!
1344
+ }
1313
1345
  `,
1314
1346
  },
1315
1347
  ],
@@ -1317,39 +1349,37 @@ const rule$4 = {
1317
1349
  schema: [
1318
1350
  {
1319
1351
  types: 'PascalCase',
1320
- fields: 'camelCase',
1321
- overrides: {
1322
- EnumValueDefinition: 'UPPER_CASE',
1323
- 'FieldDefinition[parent.name.value=Query]': {
1324
- forbiddenPrefixes: ['query', 'get'],
1325
- forbiddenSuffixes: ['Query'],
1326
- },
1327
- 'FieldDefinition[parent.name.value=Mutation]': {
1328
- forbiddenPrefixes: ['mutation'],
1329
- forbiddenSuffixes: ['Mutation'],
1330
- },
1331
- 'FieldDefinition[parent.name.value=Subscription]': {
1332
- forbiddenPrefixes: ['subscription'],
1333
- forbiddenSuffixes: ['Subscription'],
1334
- },
1352
+ FieldDefinition: 'camelCase',
1353
+ InputValueDefinition: 'camelCase',
1354
+ Argument: 'camelCase',
1355
+ DirectiveDefinition: 'camelCase',
1356
+ EnumValueDefinition: 'UPPER_CASE',
1357
+ 'FieldDefinition[parent.name.value=Query]': {
1358
+ forbiddenPrefixes: ['query', 'get'],
1359
+ forbiddenSuffixes: ['Query'],
1360
+ },
1361
+ 'FieldDefinition[parent.name.value=Mutation]': {
1362
+ forbiddenPrefixes: ['mutation'],
1363
+ forbiddenSuffixes: ['Mutation'],
1364
+ },
1365
+ 'FieldDefinition[parent.name.value=Subscription]': {
1366
+ forbiddenPrefixes: ['subscription'],
1367
+ forbiddenSuffixes: ['Subscription'],
1335
1368
  },
1336
1369
  },
1337
1370
  ],
1338
1371
  operations: [
1339
1372
  {
1340
- overrides: {
1341
- Argument: 'camelCase',
1342
- VariableDefinition: 'camelCase',
1343
- OperationDefinition: {
1344
- style: 'PascalCase',
1345
- forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
1346
- forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
1347
- },
1348
- FragmentDefinition: {
1349
- style: 'PascalCase',
1350
- forbiddenPrefixes: ['Fragment'],
1351
- forbiddenSuffixes: ['Fragment'],
1352
- },
1373
+ VariableDefinition: 'camelCase',
1374
+ OperationDefinition: {
1375
+ style: 'PascalCase',
1376
+ forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'],
1377
+ forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'],
1378
+ },
1379
+ FragmentDefinition: {
1380
+ style: 'PascalCase',
1381
+ forbiddenPrefixes: ['Fragment'],
1382
+ forbiddenSuffixes: ['Fragment'],
1353
1383
  },
1354
1384
  },
1355
1385
  ],
@@ -1391,12 +1421,15 @@ const rule$4 = {
1391
1421
  properties: {
1392
1422
  types: {
1393
1423
  ...schemaOption$1,
1394
- description: `Includes:\n\n${TYPES_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`).join('\n')}`,
1395
- },
1396
- fields: {
1397
- ...schemaOption$1,
1398
- description: `Includes:\n\n${FIELDS_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`).join('\n')}`,
1424
+ description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
1399
1425
  },
1426
+ ...Object.fromEntries(ALLOWED_KINDS.map(kind => [
1427
+ kind,
1428
+ {
1429
+ ...schemaOption$1,
1430
+ description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`,
1431
+ },
1432
+ ])),
1400
1433
  allowLeadingUnderscore: {
1401
1434
  type: 'boolean',
1402
1435
  default: false,
@@ -1405,36 +1438,25 @@ const rule$4 = {
1405
1438
  type: 'boolean',
1406
1439
  default: false,
1407
1440
  },
1408
- overrides: {
1409
- type: 'object',
1410
- additionalProperties: false,
1411
- description: [
1412
- 'May contain the following `ASTNode` names:',
1413
- '',
1414
- ...ALLOWED_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`),
1415
- '',
1416
- "> It's also possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with `ASTNode` name",
1417
- '>',
1418
- '> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`',
1419
- ].join('\n'),
1420
- patternProperties: {
1421
- [`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
1422
- },
1423
- },
1424
1441
  },
1442
+ patternProperties: {
1443
+ [`^(${ALLOWED_KINDS.join('|')})(.+)?$`]: schemaOption$1,
1444
+ },
1445
+ description: [
1446
+ "> It's possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with allowed `ASTNode` names which are described below.",
1447
+ '>',
1448
+ '> Paste or drop code into the editor in [ASTExplorer](https://astexplorer.net) and inspect the generated AST to compose your selector.',
1449
+ '>',
1450
+ '> Example: pattern property `FieldDefinition[parent.name.value=Query]` will match only fields for type `Query`.',
1451
+ ].join('\n'),
1425
1452
  },
1426
1453
  },
1427
1454
  },
1428
1455
  create(context) {
1429
- const options = {
1430
- overrides: {},
1431
- ...context.options[0],
1432
- };
1456
+ const options = context.options[0] || {};
1457
+ const { allowLeadingUnderscore, allowTrailingUnderscore, types, ...restOptions } = options;
1433
1458
  function normalisePropertyOption(kind) {
1434
- let style = options.overrides[kind];
1435
- if (!style) {
1436
- style = TYPES_KINDS.includes(kind) ? options.types : options.fields;
1437
- }
1459
+ const style = restOptions[kind] || types;
1438
1460
  return typeof style === 'object' ? style : { style };
1439
1461
  }
1440
1462
  const checkNode = (selector) => (node) => {
@@ -1454,10 +1476,10 @@ const rule$4 = {
1454
1476
  }
1455
1477
  function getErrorMessage() {
1456
1478
  let name = nodeName;
1457
- if (options.allowLeadingUnderscore) {
1479
+ if (allowLeadingUnderscore) {
1458
1480
  name = name.replace(/^_*/, '');
1459
1481
  }
1460
- if (options.allowTrailingUnderscore) {
1482
+ if (allowTrailingUnderscore) {
1461
1483
  name = name.replace(/_*$/, '');
1462
1484
  }
1463
1485
  if (prefix && !name.startsWith(prefix)) {
@@ -1491,15 +1513,13 @@ const rule$4 = {
1491
1513
  });
1492
1514
  };
1493
1515
  const listeners = {};
1494
- if (!options.allowLeadingUnderscore) {
1516
+ if (!allowLeadingUnderscore) {
1495
1517
  listeners['Name[value=/^_/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
1496
1518
  }
1497
- if (!options.allowTrailingUnderscore) {
1519
+ if (!allowTrailingUnderscore) {
1498
1520
  listeners['Name[value=/_$/]:matches([parent.kind!=Field], [parent.kind=Field][parent.alias])'] = checkUnderscore;
1499
1521
  }
1500
- const selectors = new Set([options.types && TYPES_KINDS, options.fields && FIELDS_KINDS, Object.keys(options.overrides)]
1501
- .flat()
1502
- .filter(Boolean));
1522
+ const selectors = new Set([types && TYPES_KINDS, Object.keys(restOptions)].flat().filter(Boolean));
1503
1523
  for (const selector of selectors) {
1504
1524
  listeners[selector] = checkNode(selector);
1505
1525
  }
@@ -1904,18 +1924,18 @@ const rule$9 = {
1904
1924
  },
1905
1925
  };
1906
1926
 
1907
- const ROOT_TYPES = ['query', 'mutation', 'subscription'];
1927
+ const ROOT_TYPES = ['mutation', 'subscription'];
1908
1928
  const rule$a = {
1909
1929
  meta: {
1910
1930
  type: 'suggestion',
1911
1931
  docs: {
1912
1932
  category: 'Schema',
1913
- description: 'Disallow using root types for `read-only` or `write-only` schemas.',
1933
+ description: 'Disallow using root types `mutation` and/or `subscription`.',
1914
1934
  url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-root-type.md',
1915
1935
  requiresSchema: true,
1916
1936
  examples: [
1917
1937
  {
1918
- title: 'Incorrect (`read-only` schema)',
1938
+ title: 'Incorrect',
1919
1939
  usage: [{ disallow: ['mutation', 'subscription'] }],
1920
1940
  code: /* GraphQL */ `
1921
1941
  type Mutation {
@@ -1924,16 +1944,7 @@ const rule$a = {
1924
1944
  `,
1925
1945
  },
1926
1946
  {
1927
- title: 'Incorrect (`write-only` schema)',
1928
- usage: [{ disallow: ['query'] }],
1929
- code: /* GraphQL */ `
1930
- type Query {
1931
- users: [User!]!
1932
- }
1933
- `,
1934
- },
1935
- {
1936
- title: 'Correct (`read-only` schema)',
1947
+ title: 'Correct',
1937
1948
  usage: [{ disallow: ['mutation', 'subscription'] }],
1938
1949
  code: /* GraphQL */ `
1939
1950
  type Query {
@@ -1968,7 +1979,6 @@ const rule$a = {
1968
1979
  const schema = requireGraphQLSchemaFromContext('no-root-type', context);
1969
1980
  const disallow = new Set(context.options[0].disallow);
1970
1981
  const rootTypeNames = [
1971
- disallow.has('query') && schema.getQueryType(),
1972
1982
  disallow.has('mutation') && schema.getMutationType(),
1973
1983
  disallow.has('subscription') && schema.getSubscriptionType(),
1974
1984
  ]
@@ -2548,7 +2558,7 @@ const rule$h = {
2548
2558
  examples: [
2549
2559
  {
2550
2560
  title: 'Incorrect',
2551
- usage: [{ types: true, overrides: { FieldDefinition: true } }],
2561
+ usage: [{ types: true, FieldDefinition: true }],
2552
2562
  code: /* GraphQL */ `
2553
2563
  type someTypeName {
2554
2564
  name: String
@@ -2557,7 +2567,7 @@ const rule$h = {
2557
2567
  },
2558
2568
  {
2559
2569
  title: 'Correct',
2560
- usage: [{ types: true, overrides: { FieldDefinition: true } }],
2570
+ usage: [{ types: true, FieldDefinition: true }],
2561
2571
  code: /* GraphQL */ `
2562
2572
  """
2563
2573
  Some type description
@@ -2574,11 +2584,10 @@ const rule$h = {
2574
2584
  configOptions: [
2575
2585
  {
2576
2586
  types: true,
2577
- overrides: {
2578
- [graphql.Kind.DIRECTIVE_DEFINITION]: true,
2579
- },
2587
+ [graphql.Kind.DIRECTIVE_DEFINITION]: true,
2580
2588
  },
2581
2589
  ],
2590
+ recommended: true,
2582
2591
  },
2583
2592
  type: 'suggestion',
2584
2593
  messages: {
@@ -2595,22 +2604,23 @@ const rule$h = {
2595
2604
  properties: {
2596
2605
  types: {
2597
2606
  type: 'boolean',
2598
- description: `Includes:\n\n${TYPES_KINDS.map(kind => `- [${kind}](https://spec.graphql.org/October2021/#${kind})`).join('\n')}`,
2599
- },
2600
- overrides: {
2601
- type: 'object',
2602
- description: 'Configuration for precise `ASTNode`',
2603
- additionalProperties: false,
2604
- properties: Object.fromEntries(ALLOWED_KINDS$1.map(kind => [kind, { type: 'boolean' }])),
2607
+ description: `Includes:\n\n${TYPES_KINDS.map(kind => `- \`${kind}\``).join('\n')}`,
2605
2608
  },
2609
+ ...Object.fromEntries([...ALLOWED_KINDS$1].sort().map(kind => [
2610
+ kind,
2611
+ {
2612
+ type: 'boolean',
2613
+ description: `Read more about this kind on [spec.graphql.org](https://spec.graphql.org/October2021/#${kind}).`,
2614
+ },
2615
+ ])),
2606
2616
  },
2607
2617
  },
2608
2618
  },
2609
2619
  },
2610
2620
  create(context) {
2611
- const { types, overrides = {} } = context.options[0];
2621
+ const { types, ...restOptions } = context.options[0];
2612
2622
  const kinds = new Set(types ? TYPES_KINDS : []);
2613
- for (const [kind, isEnabled] of Object.entries(overrides)) {
2623
+ for (const [kind, isEnabled] of Object.entries(restOptions)) {
2614
2624
  if (isEnabled) {
2615
2625
  kinds.add(kind);
2616
2626
  }