@graphql-eslint/eslint-plugin 3.3.0-alpha-d23e9e2.0 → 3.4.0-alpha-c01d913.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/README.md CHANGED
@@ -42,7 +42,7 @@ npm install --save-dev @graphql-eslint/eslint-plugin
42
42
 
43
43
  > Make sure you have `graphql` dependency in your project.
44
44
 
45
- ### Configuration
45
+ ## Configuration
46
46
 
47
47
  To get started, define an override in your ESLint config to apply this plugin to `.graphql` files. Add the [rules](docs/README.md) you want applied.
48
48
 
@@ -65,7 +65,7 @@ To get started, define an override in your ESLint config to apply this plugin to
65
65
 
66
66
  If your GraphQL definitions are defined only in `.graphql` files, and you're only using rules that apply to individual files, you should be good to go 👍. If you would like use a remote schema or use rules that apply across the entire collection of definitions at once, see [here](#using-a-remote-schema-or-rules-with-constraints-that-span-the-entire-schema).
67
67
 
68
- #### Tell ESLint to apply this plugin to GraphQL definitions defined in code files
68
+ ### Apply this plugin to GraphQL definitions defined in code files
69
69
 
70
70
  If you are defining GraphQL schema or GraphQL operations in code files, you'll want to define an additional override to extend the functionality of this plugin to the schema and operations in those files.
71
71
 
@@ -90,7 +90,7 @@ If you are defining GraphQL schema or GraphQL operations in code files, you'll w
90
90
 
91
91
  Under the hood, specifying the `@graphql-eslint/graphql` processor for code files will cause `graphql-eslint/graphql` to extract the schema and operation definitions from these files into virtual GraphQL documents with `.graphql` extensions. This will allow the overrides you've defined for `.graphql` files, via `"files": ["*.graphql"]`, to get applied to the definitions defined in your code files.
92
92
 
93
- #### Using a remote schema or rules with constraints that span the entire schema
93
+ ### Extended linting rules with GraphQL Schema
94
94
 
95
95
  Some rules require an understanding of the entire schema at once. For example, [no-unreachable-types](https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/no-unreachable-types.md#no-unreachable-types) checks that all types are reachable by root-level fields.
96
96
 
@@ -120,7 +120,7 @@ The parser allows you to specify a json file / graphql files(s) / url / raw stri
120
120
 
121
121
  > Some rules require type information to operate, it's marked in the docs for each rule!
122
122
 
123
- #### Extended linting rules with siblings operations
123
+ ### Extended linting rules with siblings operations
124
124
 
125
125
  While implementing this tool, we had to find solutions for a better integration of the GraphQL ecosystem and ESLint core.
126
126
 
@@ -180,7 +180,7 @@ You can find a list of [ESLint directives here](https://eslint.org/docs/2.13.1/u
180
180
 
181
181
  You can find a complete list of [all available rules here](docs/README.md).
182
182
 
183
- ## Deprecated Rules
183
+ ### Deprecated Rules
184
184
 
185
185
  See [docs/deprecated-rules.md](docs/deprecated-rules.md).
186
186
 
@@ -201,7 +201,7 @@ See [docs/deprecated-rules.md](docs/deprecated-rules.md).
201
201
 
202
202
  > If you are in a monorepo project, you probably need both sets of rules.
203
203
 
204
- ## Config usage
204
+ ### Config usage
205
205
 
206
206
  For example, to enable the `schema-recommended` config, enable it in your `.eslintrc` file with the `extends` option:
207
207
 
@@ -71,6 +71,18 @@ type Query {
71
71
  }
72
72
  ```
73
73
 
74
+ ### Correct
75
+
76
+ ```graphql
77
+ # eslint @graphql-eslint/naming-convention: ['error', { FieldDefinition: { style: 'camelCase', ignorePattern: '^(EAN13|UPC|UK)' } }]
78
+
79
+ type Product {
80
+ EAN13: String
81
+ UPC: String
82
+ UKFlag: String
83
+ }
84
+ ```
85
+
74
86
  ## Config Schema
75
87
 
76
88
  > It's possible to use a [`selector`](https://eslint.org/docs/developer-guide/selectors) that starts with allowed `ASTNode` names which are described below.
@@ -276,6 +288,10 @@ Additional restrictions:
276
288
  * Minimum items: `1`
277
289
  * Unique items: `true`
278
290
 
291
+ ### `ignorePattern` (string)
292
+
293
+ Option to skip validation of some words, e.g. acronyms
294
+
279
295
  ## Resources
280
296
 
281
297
  - [Rule source](../../packages/plugin/src/rules/naming-convention.ts)
@@ -2,7 +2,7 @@
2
2
 
3
3
  - Category: `Schema`
4
4
  - Rule name: `@graphql-eslint/unique-enum-value-names`
5
- - Requires GraphQL Schema: `false` [ℹ️](../../README.md#extended-linting-rules-with-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 GraphQL enum type is only valid if all its values are uniquely named.
@@ -4,7 +4,7 @@
4
4
 
5
5
  - Category: `Schema`
6
6
  - Rule name: `@graphql-eslint/unique-field-definition-names`
7
- - Requires GraphQL Schema: `false` [ℹ️](../../README.md#extended-linting-rules-with-graphql-schema)
7
+ - Requires GraphQL Schema: `true` [ℹ️](../../README.md#extended-linting-rules-with-graphql-schema)
8
8
  - Requires GraphQL Operations: `false` [ℹ️](../../README.md#extended-linting-rules-with-siblings-operations)
9
9
 
10
10
  A GraphQL complex type is only valid if all its fields are uniquely named.
@@ -1,3 +1,4 @@
1
1
  import { GraphQLConfig } from 'graphql-config';
2
2
  import { ParserOptions } from './types';
3
+ export declare function loadCachedGraphQLConfig(options: ParserOptions): GraphQLConfig;
3
4
  export declare function loadGraphQLConfig(options: ParserOptions): GraphQLConfig;
package/index.js CHANGED
@@ -10,10 +10,11 @@ const fs = require('fs');
10
10
  const path = require('path');
11
11
  const utils = require('@graphql-tools/utils');
12
12
  const lowerCase = _interopDefault(require('lodash.lowercase'));
13
- const depthLimit = _interopDefault(require('graphql-depth-limit'));
14
- const graphqlTagPluck = require('@graphql-tools/graphql-tag-pluck');
13
+ const chalk = _interopDefault(require('chalk'));
15
14
  const graphqlConfig = require('graphql-config');
16
15
  const codeFileLoader = require('@graphql-tools/code-file-loader');
16
+ const depthLimit = _interopDefault(require('graphql-depth-limit'));
17
+ const graphqlTagPluck = require('@graphql-tools/graphql-tag-pluck');
17
18
  const eslint = require('eslint');
18
19
  const codeFrame = require('@babel/code-frame');
19
20
 
@@ -174,6 +175,47 @@ const configs = {
174
175
  'operations-all': operationsAllConfig,
175
176
  };
176
177
 
178
+ let graphQLConfig;
179
+ function loadCachedGraphQLConfig(options) {
180
+ // We don't want cache config on test environment
181
+ // Otherwise schema and documents will be same for all tests
182
+ if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
183
+ return graphQLConfig;
184
+ }
185
+ graphQLConfig = loadGraphQLConfig(options);
186
+ return graphQLConfig;
187
+ }
188
+ function loadGraphQLConfig(options) {
189
+ const onDiskConfig = options.skipGraphQLConfig
190
+ ? null
191
+ : graphqlConfig.loadConfigSync({
192
+ throwOnEmpty: false,
193
+ throwOnMissing: false,
194
+ extensions: [addCodeFileLoaderExtension],
195
+ });
196
+ const configOptions = options.projects
197
+ ? { projects: options.projects }
198
+ : {
199
+ schema: (options.schema || ''),
200
+ documents: options.documents || options.operations,
201
+ extensions: options.extensions,
202
+ include: options.include,
203
+ exclude: options.exclude,
204
+ };
205
+ graphQLConfig =
206
+ onDiskConfig ||
207
+ new graphqlConfig.GraphQLConfig({
208
+ config: configOptions,
209
+ filepath: 'virtual-config',
210
+ }, [addCodeFileLoaderExtension]);
211
+ return graphQLConfig;
212
+ }
213
+ const addCodeFileLoaderExtension = api => {
214
+ api.loaders.schema.register(new codeFileLoader.CodeFileLoader());
215
+ api.loaders.documents.register(new codeFileLoader.CodeFileLoader());
216
+ return { name: 'graphql-eslint-loaders' };
217
+ };
218
+
177
219
  function requireSiblingsOperations(ruleName, context) {
178
220
  if (!context.parserServices) {
179
221
  throw new Error(`Rule '${ruleName}' requires 'parserOptions.operations' to be set and loaded. See http://bit.ly/graphql-eslint-operations for more info`);
@@ -192,6 +234,43 @@ function requireGraphQLSchemaFromContext(ruleName, context) {
192
234
  }
193
235
  return context.parserServices.schema;
194
236
  }
237
+ const logger = {
238
+ // eslint-disable-next-line no-console
239
+ error: (...args) => console.error(chalk.red('error'), '[graphql-eslint]', chalk(...args)),
240
+ // eslint-disable-next-line no-console
241
+ warn: (...args) => console.warn(chalk.yellow('warning'), '[graphql-eslint]', chalk(...args)),
242
+ };
243
+ const schemaToExtendCache = new Map();
244
+ const getGraphQLSchemaToExtend = (ruleId, context) => {
245
+ // If schema is not loaded, there is no reason to make partial schema aka schemaToExtend
246
+ if (!context.parserServices.hasTypeInfo) {
247
+ if (!getGraphQLSchemaToExtend.warningPrintedMap[ruleId]) {
248
+ logger.warn(`Rule "${ruleId}" works best with schema loaded. See http://bit.ly/graphql-eslint-schema for more info`);
249
+ getGraphQLSchemaToExtend.warningPrintedMap[ruleId] = true;
250
+ }
251
+ return null;
252
+ }
253
+ const filename = context.getPhysicalFilename();
254
+ if (!schemaToExtendCache.has(filename)) {
255
+ const { schema, schemaOptions } = context.parserOptions;
256
+ const gqlConfig = loadGraphQLConfig({ schema });
257
+ const projectForFile = gqlConfig.getProjectForFile(filename);
258
+ let schemaToExtend;
259
+ try {
260
+ schemaToExtend = projectForFile.loadSchemaSync(projectForFile.schema, 'GraphQLSchema', {
261
+ ...schemaOptions,
262
+ ignore: filename,
263
+ });
264
+ }
265
+ catch (_a) {
266
+ // If error throws just ignore it because maybe schema is located in 1 file
267
+ schemaToExtend = null;
268
+ }
269
+ schemaToExtendCache.set(filename, schemaToExtend);
270
+ }
271
+ return schemaToExtendCache.get(filename);
272
+ };
273
+ getGraphQLSchemaToExtend.warningPrintedMap = Object.create(null);
195
274
  function requireReachableTypesFromContext(ruleName, context) {
196
275
  const schema = requireGraphQLSchemaFromContext(ruleName, context);
197
276
  return context.parserServices.reachableTypes(schema);
@@ -442,11 +521,16 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode) => {
442
521
  },
443
522
  create(context) {
444
523
  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...`);
524
+ logger.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
525
  return {};
448
526
  }
449
- const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
527
+ let schema;
528
+ if (docs.requiresSchemaToExtend) {
529
+ schema = getGraphQLSchemaToExtend(ruleId, context);
530
+ }
531
+ else if (docs.requiresSchema) {
532
+ schema = requireGraphQLSchemaFromContext(ruleId, context);
533
+ }
450
534
  return {
451
535
  Document(node) {
452
536
  const documentNode = getDocumentNode
@@ -632,9 +716,13 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
632
716
  category: 'Schema',
633
717
  description: `A GraphQL enum type is only valid if all its values are uniquely named.`,
634
718
  recommended: false,
719
+ requiresSchema: true,
720
+ requiresSchemaToExtend: true,
635
721
  }), validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
636
722
  category: 'Schema',
637
723
  description: `A GraphQL complex type is only valid if all its fields are uniquely named.`,
724
+ requiresSchema: true,
725
+ requiresSchemaToExtend: true,
638
726
  }), validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
639
727
  category: 'Operations',
640
728
  description: `A GraphQL input object value is only valid if all supplied fields are uniquely named.`,
@@ -1376,6 +1464,17 @@ const rule$4 = {
1376
1464
  type Query {
1377
1465
  users: [User!]!
1378
1466
  }
1467
+ `,
1468
+ },
1469
+ {
1470
+ title: 'Correct',
1471
+ usage: [{ FieldDefinition: { style: 'camelCase', ignorePattern: '^(EAN13|UPC|UK)' } }],
1472
+ code: /* GraphQL */ `
1473
+ type Product {
1474
+ EAN13: String
1475
+ UPC: String
1476
+ UKFlag: String
1477
+ }
1379
1478
  `,
1380
1479
  },
1381
1480
  ],
@@ -1445,6 +1544,10 @@ const rule$4 = {
1445
1544
  minItems: 1,
1446
1545
  items: { type: 'string' },
1447
1546
  },
1547
+ ignorePattern: {
1548
+ type: 'string',
1549
+ description: 'Option to skip validation of some words, e.g. acronyms',
1550
+ },
1448
1551
  },
1449
1552
  },
1450
1553
  },
@@ -1499,15 +1602,15 @@ const rule$4 = {
1499
1602
  if (!node) {
1500
1603
  return;
1501
1604
  }
1502
- const { prefix, suffix, forbiddenPrefixes, forbiddenSuffixes, style } = normalisePropertyOption(selector);
1605
+ const { prefix, suffix, forbiddenPrefixes, forbiddenSuffixes, style, ignorePattern } = normalisePropertyOption(selector);
1503
1606
  const nodeType = KindToDisplayName[n.kind] || n.kind;
1504
1607
  const nodeName = node.value;
1505
1608
  const error = getError();
1506
1609
  if (error) {
1507
1610
  const { errorMessage, renameToName } = error;
1508
- const [leadingUnderscore] = nodeName.match(/^_*/);
1509
- const [trailingUnderscore] = nodeName.match(/_*$/);
1510
- const suggestedName = leadingUnderscore + renameToName + trailingUnderscore;
1611
+ const [leadingUnderscores] = nodeName.match(/^_*/);
1612
+ const [trailingUnderscores] = nodeName.match(/_*$/);
1613
+ const suggestedName = leadingUnderscores + renameToName + trailingUnderscores;
1511
1614
  context.report({
1512
1615
  loc: getLocation(node.loc, node.value),
1513
1616
  message: `${nodeType} "${nodeName}" should ${errorMessage}`,
@@ -1521,6 +1624,9 @@ const rule$4 = {
1521
1624
  }
1522
1625
  function getError() {
1523
1626
  const name = nodeName.replace(/(^_+)|(_+$)/g, '');
1627
+ if (ignorePattern && new RegExp(ignorePattern, 'u').test(name)) {
1628
+ return;
1629
+ }
1524
1630
  if (prefix && !name.startsWith(prefix)) {
1525
1631
  return {
1526
1632
  errorMessage: `have "${prefix}" prefix`,
@@ -1547,8 +1653,12 @@ const rule$4 = {
1547
1653
  renameToName: name.replace(new RegExp(`${forbiddenSuffix}$`), ''),
1548
1654
  };
1549
1655
  }
1656
+ // Style is optional
1657
+ if (!style) {
1658
+ return;
1659
+ }
1550
1660
  const caseRegex = StyleToRegex[style];
1551
- if (caseRegex && !caseRegex.test(name)) {
1661
+ if (!caseRegex.test(name)) {
1552
1662
  return {
1553
1663
  errorMessage: `be in ${style} format`,
1554
1664
  renameToName: convertCase(style, name),
@@ -3015,12 +3125,13 @@ const rule$j = {
3015
3125
  },
3016
3126
  };
3017
3127
 
3128
+ const RULE_ID$2 = 'selection-set-depth';
3018
3129
  const rule$k = {
3019
3130
  meta: {
3020
3131
  docs: {
3021
3132
  category: 'Operations',
3022
3133
  description: `Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://github.com/stems/graphql-depth-limit).`,
3023
- url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/selection-set-depth.md',
3134
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID$2}.md`,
3024
3135
  requiresSiblings: true,
3025
3136
  examples: [
3026
3137
  {
@@ -3094,11 +3205,10 @@ const rule$k = {
3094
3205
  create(context) {
3095
3206
  let siblings = null;
3096
3207
  try {
3097
- siblings = requireSiblingsOperations('selection-set-depth', context);
3208
+ siblings = requireSiblingsOperations(RULE_ID$2, context);
3098
3209
  }
3099
3210
  catch (e) {
3100
- // eslint-disable-next-line no-console
3101
- console.warn(`Rule "selection-set-depth" works best with siblings operations loaded. For more info: http://bit.ly/graphql-eslint-operations`);
3211
+ logger.warn(`Rule "${RULE_ID$2}" works best with siblings operations loaded. For more info: http://bit.ly/graphql-eslint-operations`);
3102
3212
  }
3103
3213
  const { maxDepth } = context.options[0];
3104
3214
  const ignore = context.options[0].ignore || [];
@@ -3123,8 +3233,7 @@ const rule$k = {
3123
3233
  });
3124
3234
  }
3125
3235
  catch (e) {
3126
- // eslint-disable-next-line no-console
3127
- console.warn(`Rule "selection-set-depth" check failed due to a missing siblings operations. For more info: http://bit.ly/graphql-eslint-operations`, e);
3236
+ logger.warn(`Rule "${RULE_ID$2}" check failed due to a missing siblings operations. For more info: http://bit.ly/graphql-eslint-operations`, e);
3128
3237
  }
3129
3238
  },
3130
3239
  };
@@ -3506,8 +3615,7 @@ function createGraphqlProcessor() {
3506
3615
  }
3507
3616
  }
3508
3617
  catch (e) {
3509
- // eslint-disable-next-line no-console
3510
- console.warn(`[graphql-eslint/processor]: Unable to process file "${filename}": `, e);
3618
+ logger.warn(`Unable to process file "${filename}"`, e);
3511
3619
  }
3512
3620
  }
3513
3621
  return [text];
@@ -3547,20 +3655,25 @@ const schemaCache = new Map();
3547
3655
  function getSchema(options = {}, gqlConfig) {
3548
3656
  const realFilepath = options.filePath ? getOnDiskFilepath(options.filePath) : null;
3549
3657
  const projectForFile = realFilepath ? gqlConfig.getProjectForFile(realFilepath) : gqlConfig.getDefault();
3550
- const schemaKey = utils.asArray(projectForFile.schema)
3551
- .sort()
3552
- .join(',');
3658
+ const schemaKey = utils.asArray(projectForFile.schema).sort().join(',');
3553
3659
  if (!schemaKey) {
3554
3660
  return null;
3555
3661
  }
3556
- let schema = schemaCache.get(schemaKey);
3557
- if (!schema) {
3662
+ if (schemaCache.has(schemaKey)) {
3663
+ return schemaCache.get(schemaKey);
3664
+ }
3665
+ let schema;
3666
+ try {
3558
3667
  schema = projectForFile.loadSchemaSync(projectForFile.schema, 'GraphQLSchema', {
3559
3668
  cache: loaderCache,
3560
- ...options.schemaOptions
3669
+ ...options.schemaOptions,
3561
3670
  });
3562
- schemaCache.set(schemaKey, schema);
3563
3671
  }
3672
+ catch (e) {
3673
+ schema = null;
3674
+ logger.error('Error while loading schema\n', e);
3675
+ }
3676
+ schemaCache.set(schemaKey, schema);
3564
3677
  return schema;
3565
3678
  }
3566
3679
 
@@ -3573,10 +3686,10 @@ const handleVirtualPath = (documents) => {
3573
3686
  return source;
3574
3687
  }
3575
3688
  (_a = filepathMap[location]) !== null && _a !== void 0 ? _a : (filepathMap[location] = -1);
3576
- const index = filepathMap[location] += 1;
3689
+ const index = (filepathMap[location] += 1);
3577
3690
  return {
3578
3691
  ...source,
3579
- location: path.resolve(location, `${index}_document.graphql`)
3692
+ location: path.resolve(location, `${index}_document.graphql`),
3580
3693
  };
3581
3694
  });
3582
3695
  };
@@ -3585,9 +3698,7 @@ const siblingOperationsCache = new Map();
3585
3698
  const getSiblings = (filePath, gqlConfig) => {
3586
3699
  const realFilepath = filePath ? getOnDiskFilepath(filePath) : null;
3587
3700
  const projectForFile = realFilepath ? gqlConfig.getProjectForFile(realFilepath) : gqlConfig.getDefault();
3588
- const documentsKey = utils.asArray(projectForFile.documents)
3589
- .sort()
3590
- .join(',');
3701
+ const documentsKey = utils.asArray(projectForFile.documents).sort().join(',');
3591
3702
  if (!documentsKey) {
3592
3703
  return [];
3593
3704
  }
@@ -3595,7 +3706,7 @@ const getSiblings = (filePath, gqlConfig) => {
3595
3706
  if (!siblings) {
3596
3707
  const documents = projectForFile.loadDocumentsSync(projectForFile.documents, {
3597
3708
  skipGraphQLImport: true,
3598
- cache: loaderCache
3709
+ cache: loaderCache,
3599
3710
  });
3600
3711
  siblings = handleVirtualPath(documents);
3601
3712
  operationsCache.set(documentsKey, siblings);
@@ -3608,8 +3719,7 @@ function getSiblingOperations(options, gqlConfig) {
3608
3719
  let printed = false;
3609
3720
  const noopWarn = () => {
3610
3721
  if (!printed) {
3611
- // eslint-disable-next-line no-console
3612
- console.warn(`getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!`);
3722
+ logger.warn(`getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!`);
3613
3723
  printed = true;
3614
3724
  }
3615
3725
  return [];
@@ -3673,8 +3783,7 @@ function getSiblingOperations(options, gqlConfig) {
3673
3783
  const name = spread.name.value;
3674
3784
  const fragmentInfo = getFragment(name);
3675
3785
  if (fragmentInfo.length === 0) {
3676
- // eslint-disable-next-line no-console
3677
- console.warn(`Unable to locate fragment named "${name}", please make sure it's loaded using "parserOptions.operations"`);
3786
+ logger.warn(`Unable to locate fragment named "${name}", please make sure it's loaded using "parserOptions.operations"`);
3678
3787
  return;
3679
3788
  }
3680
3789
  const fragment = fragmentInfo[0];
@@ -3704,43 +3813,6 @@ function getSiblingOperations(options, gqlConfig) {
3704
3813
  return siblingOperations;
3705
3814
  }
3706
3815
 
3707
- let graphQLConfig;
3708
- function loadGraphQLConfig(options) {
3709
- // We don't want cache config on test environment
3710
- // Otherwise schema and documents will be same for all tests
3711
- if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
3712
- return graphQLConfig;
3713
- }
3714
- const onDiskConfig = options.skipGraphQLConfig
3715
- ? null
3716
- : graphqlConfig.loadConfigSync({
3717
- throwOnEmpty: false,
3718
- throwOnMissing: false,
3719
- extensions: [addCodeFileLoaderExtension],
3720
- });
3721
- const configOptions = options.projects
3722
- ? { projects: options.projects }
3723
- : {
3724
- schema: (options.schema || ''),
3725
- documents: options.documents || options.operations,
3726
- extensions: options.extensions,
3727
- include: options.include,
3728
- exclude: options.exclude,
3729
- };
3730
- graphQLConfig =
3731
- onDiskConfig ||
3732
- new graphqlConfig.GraphQLConfig({
3733
- config: configOptions,
3734
- filepath: 'virtual-config',
3735
- }, [addCodeFileLoaderExtension]);
3736
- return graphQLConfig;
3737
- }
3738
- const addCodeFileLoaderExtension = api => {
3739
- api.loaders.schema.register(new codeFileLoader.CodeFileLoader());
3740
- api.loaders.documents.register(new codeFileLoader.CodeFileLoader());
3741
- return { name: 'graphql-eslint-loaders' };
3742
- };
3743
-
3744
3816
  let reachableTypesCache;
3745
3817
  function getReachableTypes(schema) {
3746
3818
  // We don't want cache reachableTypes on test environment
@@ -3823,7 +3895,7 @@ function parse(code, options) {
3823
3895
  return parseForESLint(code, options).ast;
3824
3896
  }
3825
3897
  function parseForESLint(code, options = {}) {
3826
- const gqlConfig = loadGraphQLConfig(options);
3898
+ const gqlConfig = loadCachedGraphQLConfig(options);
3827
3899
  const schema = getSchema(options, gqlConfig);
3828
3900
  const parserServices = {
3829
3901
  hasTypeInfo: schema !== null,
@@ -3855,6 +3927,7 @@ function parseForESLint(code, options = {}) {
3855
3927
  };
3856
3928
  }
3857
3929
  catch (e) {
3930
+ e.message = `[graphql-eslint] ${e.message}`;
3858
3931
  // In case of GraphQL parser error, we report it to ESLint as a parser error that matches the requirements
3859
3932
  // of ESLint. This will make sure to display it correctly in IDEs and lint results.
3860
3933
  if (e instanceof graphql.GraphQLError) {
@@ -3862,11 +3935,10 @@ function parseForESLint(code, options = {}) {
3862
3935
  index: e.positions[0],
3863
3936
  lineNumber: e.locations[0].line,
3864
3937
  column: e.locations[0].column,
3865
- message: `[graphql-eslint]: ${e.message}`,
3938
+ message: e.message,
3866
3939
  };
3867
3940
  throw eslintError;
3868
3941
  }
3869
- e.message = `[graphql-eslint]: ${e.message}`;
3870
3942
  throw e;
3871
3943
  }
3872
3944
  }
package/index.mjs CHANGED
@@ -4,10 +4,11 @@ import { statSync, existsSync, readFileSync } from 'fs';
4
4
  import { dirname, extname, basename, relative, resolve } from 'path';
5
5
  import { asArray, parseGraphQLSDL } from '@graphql-tools/utils';
6
6
  import lowerCase from 'lodash.lowercase';
7
- import depthLimit from 'graphql-depth-limit';
8
- import { parseCode } from '@graphql-tools/graphql-tag-pluck';
7
+ import chalk from 'chalk';
9
8
  import { loadConfigSync, GraphQLConfig } from 'graphql-config';
10
9
  import { CodeFileLoader } from '@graphql-tools/code-file-loader';
10
+ import depthLimit from 'graphql-depth-limit';
11
+ import { parseCode } from '@graphql-tools/graphql-tag-pluck';
11
12
  import { RuleTester, Linter } from 'eslint';
12
13
  import { codeFrameColumns } from '@babel/code-frame';
13
14
 
@@ -168,6 +169,47 @@ const configs = {
168
169
  'operations-all': operationsAllConfig,
169
170
  };
170
171
 
172
+ let graphQLConfig;
173
+ function loadCachedGraphQLConfig(options) {
174
+ // We don't want cache config on test environment
175
+ // Otherwise schema and documents will be same for all tests
176
+ if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
177
+ return graphQLConfig;
178
+ }
179
+ graphQLConfig = loadGraphQLConfig(options);
180
+ return graphQLConfig;
181
+ }
182
+ function loadGraphQLConfig(options) {
183
+ const onDiskConfig = options.skipGraphQLConfig
184
+ ? null
185
+ : loadConfigSync({
186
+ throwOnEmpty: false,
187
+ throwOnMissing: false,
188
+ extensions: [addCodeFileLoaderExtension],
189
+ });
190
+ const configOptions = options.projects
191
+ ? { projects: options.projects }
192
+ : {
193
+ schema: (options.schema || ''),
194
+ documents: options.documents || options.operations,
195
+ extensions: options.extensions,
196
+ include: options.include,
197
+ exclude: options.exclude,
198
+ };
199
+ graphQLConfig =
200
+ onDiskConfig ||
201
+ new GraphQLConfig({
202
+ config: configOptions,
203
+ filepath: 'virtual-config',
204
+ }, [addCodeFileLoaderExtension]);
205
+ return graphQLConfig;
206
+ }
207
+ const addCodeFileLoaderExtension = api => {
208
+ api.loaders.schema.register(new CodeFileLoader());
209
+ api.loaders.documents.register(new CodeFileLoader());
210
+ return { name: 'graphql-eslint-loaders' };
211
+ };
212
+
171
213
  function requireSiblingsOperations(ruleName, context) {
172
214
  if (!context.parserServices) {
173
215
  throw new Error(`Rule '${ruleName}' requires 'parserOptions.operations' to be set and loaded. See http://bit.ly/graphql-eslint-operations for more info`);
@@ -186,6 +228,43 @@ function requireGraphQLSchemaFromContext(ruleName, context) {
186
228
  }
187
229
  return context.parserServices.schema;
188
230
  }
231
+ const logger = {
232
+ // eslint-disable-next-line no-console
233
+ error: (...args) => console.error(chalk.red('error'), '[graphql-eslint]', chalk(...args)),
234
+ // eslint-disable-next-line no-console
235
+ warn: (...args) => console.warn(chalk.yellow('warning'), '[graphql-eslint]', chalk(...args)),
236
+ };
237
+ const schemaToExtendCache = new Map();
238
+ const getGraphQLSchemaToExtend = (ruleId, context) => {
239
+ // If schema is not loaded, there is no reason to make partial schema aka schemaToExtend
240
+ if (!context.parserServices.hasTypeInfo) {
241
+ if (!getGraphQLSchemaToExtend.warningPrintedMap[ruleId]) {
242
+ logger.warn(`Rule "${ruleId}" works best with schema loaded. See http://bit.ly/graphql-eslint-schema for more info`);
243
+ getGraphQLSchemaToExtend.warningPrintedMap[ruleId] = true;
244
+ }
245
+ return null;
246
+ }
247
+ const filename = context.getPhysicalFilename();
248
+ if (!schemaToExtendCache.has(filename)) {
249
+ const { schema, schemaOptions } = context.parserOptions;
250
+ const gqlConfig = loadGraphQLConfig({ schema });
251
+ const projectForFile = gqlConfig.getProjectForFile(filename);
252
+ let schemaToExtend;
253
+ try {
254
+ schemaToExtend = projectForFile.loadSchemaSync(projectForFile.schema, 'GraphQLSchema', {
255
+ ...schemaOptions,
256
+ ignore: filename,
257
+ });
258
+ }
259
+ catch (_a) {
260
+ // If error throws just ignore it because maybe schema is located in 1 file
261
+ schemaToExtend = null;
262
+ }
263
+ schemaToExtendCache.set(filename, schemaToExtend);
264
+ }
265
+ return schemaToExtendCache.get(filename);
266
+ };
267
+ getGraphQLSchemaToExtend.warningPrintedMap = Object.create(null);
189
268
  function requireReachableTypesFromContext(ruleName, context) {
190
269
  const schema = requireGraphQLSchemaFromContext(ruleName, context);
191
270
  return context.parserServices.reachableTypes(schema);
@@ -436,11 +515,16 @@ const validationToRule = (ruleId, ruleName, docs, getDocumentNode) => {
436
515
  },
437
516
  create(context) {
438
517
  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...`);
518
+ logger.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
519
  return {};
442
520
  }
443
- const schema = docs.requiresSchema ? requireGraphQLSchemaFromContext(ruleId, context) : null;
521
+ let schema;
522
+ if (docs.requiresSchemaToExtend) {
523
+ schema = getGraphQLSchemaToExtend(ruleId, context);
524
+ }
525
+ else if (docs.requiresSchema) {
526
+ schema = requireGraphQLSchemaFromContext(ruleId, context);
527
+ }
444
528
  return {
445
529
  Document(node) {
446
530
  const documentNode = getDocumentNode
@@ -626,9 +710,13 @@ const GRAPHQL_JS_VALIDATIONS = Object.assign({}, validationToRule('executable-de
626
710
  category: 'Schema',
627
711
  description: `A GraphQL enum type is only valid if all its values are uniquely named.`,
628
712
  recommended: false,
713
+ requiresSchema: true,
714
+ requiresSchemaToExtend: true,
629
715
  }), validationToRule('unique-field-definition-names', 'UniqueFieldDefinitionNames', {
630
716
  category: 'Schema',
631
717
  description: `A GraphQL complex type is only valid if all its fields are uniquely named.`,
718
+ requiresSchema: true,
719
+ requiresSchemaToExtend: true,
632
720
  }), validationToRule('unique-input-field-names', 'UniqueInputFieldNames', {
633
721
  category: 'Operations',
634
722
  description: `A GraphQL input object value is only valid if all supplied fields are uniquely named.`,
@@ -1370,6 +1458,17 @@ const rule$4 = {
1370
1458
  type Query {
1371
1459
  users: [User!]!
1372
1460
  }
1461
+ `,
1462
+ },
1463
+ {
1464
+ title: 'Correct',
1465
+ usage: [{ FieldDefinition: { style: 'camelCase', ignorePattern: '^(EAN13|UPC|UK)' } }],
1466
+ code: /* GraphQL */ `
1467
+ type Product {
1468
+ EAN13: String
1469
+ UPC: String
1470
+ UKFlag: String
1471
+ }
1373
1472
  `,
1374
1473
  },
1375
1474
  ],
@@ -1439,6 +1538,10 @@ const rule$4 = {
1439
1538
  minItems: 1,
1440
1539
  items: { type: 'string' },
1441
1540
  },
1541
+ ignorePattern: {
1542
+ type: 'string',
1543
+ description: 'Option to skip validation of some words, e.g. acronyms',
1544
+ },
1442
1545
  },
1443
1546
  },
1444
1547
  },
@@ -1493,15 +1596,15 @@ const rule$4 = {
1493
1596
  if (!node) {
1494
1597
  return;
1495
1598
  }
1496
- const { prefix, suffix, forbiddenPrefixes, forbiddenSuffixes, style } = normalisePropertyOption(selector);
1599
+ const { prefix, suffix, forbiddenPrefixes, forbiddenSuffixes, style, ignorePattern } = normalisePropertyOption(selector);
1497
1600
  const nodeType = KindToDisplayName[n.kind] || n.kind;
1498
1601
  const nodeName = node.value;
1499
1602
  const error = getError();
1500
1603
  if (error) {
1501
1604
  const { errorMessage, renameToName } = error;
1502
- const [leadingUnderscore] = nodeName.match(/^_*/);
1503
- const [trailingUnderscore] = nodeName.match(/_*$/);
1504
- const suggestedName = leadingUnderscore + renameToName + trailingUnderscore;
1605
+ const [leadingUnderscores] = nodeName.match(/^_*/);
1606
+ const [trailingUnderscores] = nodeName.match(/_*$/);
1607
+ const suggestedName = leadingUnderscores + renameToName + trailingUnderscores;
1505
1608
  context.report({
1506
1609
  loc: getLocation(node.loc, node.value),
1507
1610
  message: `${nodeType} "${nodeName}" should ${errorMessage}`,
@@ -1515,6 +1618,9 @@ const rule$4 = {
1515
1618
  }
1516
1619
  function getError() {
1517
1620
  const name = nodeName.replace(/(^_+)|(_+$)/g, '');
1621
+ if (ignorePattern && new RegExp(ignorePattern, 'u').test(name)) {
1622
+ return;
1623
+ }
1518
1624
  if (prefix && !name.startsWith(prefix)) {
1519
1625
  return {
1520
1626
  errorMessage: `have "${prefix}" prefix`,
@@ -1541,8 +1647,12 @@ const rule$4 = {
1541
1647
  renameToName: name.replace(new RegExp(`${forbiddenSuffix}$`), ''),
1542
1648
  };
1543
1649
  }
1650
+ // Style is optional
1651
+ if (!style) {
1652
+ return;
1653
+ }
1544
1654
  const caseRegex = StyleToRegex[style];
1545
- if (caseRegex && !caseRegex.test(name)) {
1655
+ if (!caseRegex.test(name)) {
1546
1656
  return {
1547
1657
  errorMessage: `be in ${style} format`,
1548
1658
  renameToName: convertCase(style, name),
@@ -3009,12 +3119,13 @@ const rule$j = {
3009
3119
  },
3010
3120
  };
3011
3121
 
3122
+ const RULE_ID$2 = 'selection-set-depth';
3012
3123
  const rule$k = {
3013
3124
  meta: {
3014
3125
  docs: {
3015
3126
  category: 'Operations',
3016
3127
  description: `Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://github.com/stems/graphql-depth-limit).`,
3017
- url: 'https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/selection-set-depth.md',
3128
+ url: `https://github.com/dotansimha/graphql-eslint/blob/master/docs/rules/${RULE_ID$2}.md`,
3018
3129
  requiresSiblings: true,
3019
3130
  examples: [
3020
3131
  {
@@ -3088,11 +3199,10 @@ const rule$k = {
3088
3199
  create(context) {
3089
3200
  let siblings = null;
3090
3201
  try {
3091
- siblings = requireSiblingsOperations('selection-set-depth', context);
3202
+ siblings = requireSiblingsOperations(RULE_ID$2, context);
3092
3203
  }
3093
3204
  catch (e) {
3094
- // eslint-disable-next-line no-console
3095
- console.warn(`Rule "selection-set-depth" works best with siblings operations loaded. For more info: http://bit.ly/graphql-eslint-operations`);
3205
+ logger.warn(`Rule "${RULE_ID$2}" works best with siblings operations loaded. For more info: http://bit.ly/graphql-eslint-operations`);
3096
3206
  }
3097
3207
  const { maxDepth } = context.options[0];
3098
3208
  const ignore = context.options[0].ignore || [];
@@ -3117,8 +3227,7 @@ const rule$k = {
3117
3227
  });
3118
3228
  }
3119
3229
  catch (e) {
3120
- // eslint-disable-next-line no-console
3121
- console.warn(`Rule "selection-set-depth" check failed due to a missing siblings operations. For more info: http://bit.ly/graphql-eslint-operations`, e);
3230
+ logger.warn(`Rule "${RULE_ID$2}" check failed due to a missing siblings operations. For more info: http://bit.ly/graphql-eslint-operations`, e);
3122
3231
  }
3123
3232
  },
3124
3233
  };
@@ -3500,8 +3609,7 @@ function createGraphqlProcessor() {
3500
3609
  }
3501
3610
  }
3502
3611
  catch (e) {
3503
- // eslint-disable-next-line no-console
3504
- console.warn(`[graphql-eslint/processor]: Unable to process file "${filename}": `, e);
3612
+ logger.warn(`Unable to process file "${filename}"`, e);
3505
3613
  }
3506
3614
  }
3507
3615
  return [text];
@@ -3541,20 +3649,25 @@ const schemaCache = new Map();
3541
3649
  function getSchema(options = {}, gqlConfig) {
3542
3650
  const realFilepath = options.filePath ? getOnDiskFilepath(options.filePath) : null;
3543
3651
  const projectForFile = realFilepath ? gqlConfig.getProjectForFile(realFilepath) : gqlConfig.getDefault();
3544
- const schemaKey = asArray(projectForFile.schema)
3545
- .sort()
3546
- .join(',');
3652
+ const schemaKey = asArray(projectForFile.schema).sort().join(',');
3547
3653
  if (!schemaKey) {
3548
3654
  return null;
3549
3655
  }
3550
- let schema = schemaCache.get(schemaKey);
3551
- if (!schema) {
3656
+ if (schemaCache.has(schemaKey)) {
3657
+ return schemaCache.get(schemaKey);
3658
+ }
3659
+ let schema;
3660
+ try {
3552
3661
  schema = projectForFile.loadSchemaSync(projectForFile.schema, 'GraphQLSchema', {
3553
3662
  cache: loaderCache,
3554
- ...options.schemaOptions
3663
+ ...options.schemaOptions,
3555
3664
  });
3556
- schemaCache.set(schemaKey, schema);
3557
3665
  }
3666
+ catch (e) {
3667
+ schema = null;
3668
+ logger.error('Error while loading schema\n', e);
3669
+ }
3670
+ schemaCache.set(schemaKey, schema);
3558
3671
  return schema;
3559
3672
  }
3560
3673
 
@@ -3567,10 +3680,10 @@ const handleVirtualPath = (documents) => {
3567
3680
  return source;
3568
3681
  }
3569
3682
  (_a = filepathMap[location]) !== null && _a !== void 0 ? _a : (filepathMap[location] = -1);
3570
- const index = filepathMap[location] += 1;
3683
+ const index = (filepathMap[location] += 1);
3571
3684
  return {
3572
3685
  ...source,
3573
- location: resolve(location, `${index}_document.graphql`)
3686
+ location: resolve(location, `${index}_document.graphql`),
3574
3687
  };
3575
3688
  });
3576
3689
  };
@@ -3579,9 +3692,7 @@ const siblingOperationsCache = new Map();
3579
3692
  const getSiblings = (filePath, gqlConfig) => {
3580
3693
  const realFilepath = filePath ? getOnDiskFilepath(filePath) : null;
3581
3694
  const projectForFile = realFilepath ? gqlConfig.getProjectForFile(realFilepath) : gqlConfig.getDefault();
3582
- const documentsKey = asArray(projectForFile.documents)
3583
- .sort()
3584
- .join(',');
3695
+ const documentsKey = asArray(projectForFile.documents).sort().join(',');
3585
3696
  if (!documentsKey) {
3586
3697
  return [];
3587
3698
  }
@@ -3589,7 +3700,7 @@ const getSiblings = (filePath, gqlConfig) => {
3589
3700
  if (!siblings) {
3590
3701
  const documents = projectForFile.loadDocumentsSync(projectForFile.documents, {
3591
3702
  skipGraphQLImport: true,
3592
- cache: loaderCache
3703
+ cache: loaderCache,
3593
3704
  });
3594
3705
  siblings = handleVirtualPath(documents);
3595
3706
  operationsCache.set(documentsKey, siblings);
@@ -3602,8 +3713,7 @@ function getSiblingOperations(options, gqlConfig) {
3602
3713
  let printed = false;
3603
3714
  const noopWarn = () => {
3604
3715
  if (!printed) {
3605
- // eslint-disable-next-line no-console
3606
- console.warn(`getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!`);
3716
+ logger.warn(`getSiblingOperations was called without any operations. Make sure to set "parserOptions.operations" to make this feature available!`);
3607
3717
  printed = true;
3608
3718
  }
3609
3719
  return [];
@@ -3667,8 +3777,7 @@ function getSiblingOperations(options, gqlConfig) {
3667
3777
  const name = spread.name.value;
3668
3778
  const fragmentInfo = getFragment(name);
3669
3779
  if (fragmentInfo.length === 0) {
3670
- // eslint-disable-next-line no-console
3671
- console.warn(`Unable to locate fragment named "${name}", please make sure it's loaded using "parserOptions.operations"`);
3780
+ logger.warn(`Unable to locate fragment named "${name}", please make sure it's loaded using "parserOptions.operations"`);
3672
3781
  return;
3673
3782
  }
3674
3783
  const fragment = fragmentInfo[0];
@@ -3698,43 +3807,6 @@ function getSiblingOperations(options, gqlConfig) {
3698
3807
  return siblingOperations;
3699
3808
  }
3700
3809
 
3701
- let graphQLConfig;
3702
- function loadGraphQLConfig(options) {
3703
- // We don't want cache config on test environment
3704
- // Otherwise schema and documents will be same for all tests
3705
- if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
3706
- return graphQLConfig;
3707
- }
3708
- const onDiskConfig = options.skipGraphQLConfig
3709
- ? null
3710
- : loadConfigSync({
3711
- throwOnEmpty: false,
3712
- throwOnMissing: false,
3713
- extensions: [addCodeFileLoaderExtension],
3714
- });
3715
- const configOptions = options.projects
3716
- ? { projects: options.projects }
3717
- : {
3718
- schema: (options.schema || ''),
3719
- documents: options.documents || options.operations,
3720
- extensions: options.extensions,
3721
- include: options.include,
3722
- exclude: options.exclude,
3723
- };
3724
- graphQLConfig =
3725
- onDiskConfig ||
3726
- new GraphQLConfig({
3727
- config: configOptions,
3728
- filepath: 'virtual-config',
3729
- }, [addCodeFileLoaderExtension]);
3730
- return graphQLConfig;
3731
- }
3732
- const addCodeFileLoaderExtension = api => {
3733
- api.loaders.schema.register(new CodeFileLoader());
3734
- api.loaders.documents.register(new CodeFileLoader());
3735
- return { name: 'graphql-eslint-loaders' };
3736
- };
3737
-
3738
3810
  let reachableTypesCache;
3739
3811
  function getReachableTypes(schema) {
3740
3812
  // We don't want cache reachableTypes on test environment
@@ -3817,7 +3889,7 @@ function parse(code, options) {
3817
3889
  return parseForESLint(code, options).ast;
3818
3890
  }
3819
3891
  function parseForESLint(code, options = {}) {
3820
- const gqlConfig = loadGraphQLConfig(options);
3892
+ const gqlConfig = loadCachedGraphQLConfig(options);
3821
3893
  const schema = getSchema(options, gqlConfig);
3822
3894
  const parserServices = {
3823
3895
  hasTypeInfo: schema !== null,
@@ -3849,6 +3921,7 @@ function parseForESLint(code, options = {}) {
3849
3921
  };
3850
3922
  }
3851
3923
  catch (e) {
3924
+ e.message = `[graphql-eslint] ${e.message}`;
3852
3925
  // In case of GraphQL parser error, we report it to ESLint as a parser error that matches the requirements
3853
3926
  // of ESLint. This will make sure to display it correctly in IDEs and lint results.
3854
3927
  if (e instanceof GraphQLError) {
@@ -3856,11 +3929,10 @@ function parseForESLint(code, options = {}) {
3856
3929
  index: e.positions[0],
3857
3930
  lineNumber: e.locations[0].line,
3858
3931
  column: e.locations[0].column,
3859
- message: `[graphql-eslint]: ${e.message}`,
3932
+ message: e.message,
3860
3933
  };
3861
3934
  throw eslintError;
3862
3935
  }
3863
- e.message = `[graphql-eslint]: ${e.message}`;
3864
3936
  throw e;
3865
3937
  }
3866
3938
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "3.3.0-alpha-d23e9e2.0",
3
+ "version": "3.4.0-alpha-c01d913.0",
4
4
  "description": "GraphQL plugin for ESLint",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
@@ -11,6 +11,7 @@
11
11
  "@graphql-tools/code-file-loader": "7.2.3",
12
12
  "@graphql-tools/graphql-tag-pluck": "7.1.4",
13
13
  "@graphql-tools/utils": "8.5.5",
14
+ "chalk": "4.1.2",
14
15
  "graphql-config": "4.1.0",
15
16
  "graphql-depth-limit": "1.1.0",
16
17
  "lodash.lowercase": "4.3.0"
@@ -23,6 +23,7 @@ declare type PropertySchema = {
23
23
  prefix?: string;
24
24
  forbiddenPrefixes?: string[];
25
25
  forbiddenSuffixes?: string[];
26
+ ignorePattern?: string;
26
27
  };
27
28
  declare type Options = AllowedStyle | PropertySchema;
28
29
  export declare type NamingConventionRuleConfig = {
package/utils.d.ts CHANGED
@@ -6,6 +6,15 @@ import { SiblingOperations } from './sibling-operations';
6
6
  import { UsedFields, ReachableTypes } from './graphql-ast';
7
7
  export declare function requireSiblingsOperations(ruleName: string, context: GraphQLESLintRuleContext): SiblingOperations | never;
8
8
  export declare function requireGraphQLSchemaFromContext(ruleName: string, context: GraphQLESLintRuleContext): GraphQLSchema | never;
9
+ export declare const logger: {
10
+ error: (...args: any[]) => void;
11
+ warn: (...args: any[]) => void;
12
+ };
13
+ declare type GetGraphQLSchemaToExtend = {
14
+ (ruleId: string, ctx: GraphQLESLintRuleContext): GraphQLSchema | null;
15
+ warningPrintedMap: Record<string, boolean>;
16
+ };
17
+ export declare const getGraphQLSchemaToExtend: GetGraphQLSchemaToExtend;
9
18
  export declare function requireReachableTypesFromContext(ruleName: string, context: GraphQLESLintRuleContext): ReachableTypes | never;
10
19
  export declare function requireUsedFieldsFromContext(ruleName: string, context: GraphQLESLintRuleContext): UsedFields | never;
11
20
  export declare function extractTokens(source: Source): AST.Token[];
@@ -27,3 +36,4 @@ export declare function getLocation(loc: Partial<AST.SourceLocation>, fieldName?
27
36
  offsetStart?: number;
28
37
  offsetEnd?: number;
29
38
  }): AST.SourceLocation;
39
+ export {};