@graphql-eslint/eslint-plugin 3.12.0-alpha-20220929103858-c00a837 → 3.12.0-alpha-20221008232037-33da317

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
1
  import { GraphQLConfig } from 'graphql-config';
2
2
  import { ParserOptions } from './types';
3
3
  export declare function loadOnDiskGraphQLConfig(filePath: string): GraphQLConfig;
4
- export declare function loadGraphQLConfig(options?: ParserOptions): GraphQLConfig;
4
+ export declare function loadGraphQLConfig(options: ParserOptions): GraphQLConfig;
package/index.js CHANGED
@@ -24,15 +24,24 @@ const codeFrame = require('@babel/code-frame');
24
24
  const debug = debugFactory('graphql-eslint:graphql-config');
25
25
  let graphQLConfig;
26
26
  function loadOnDiskGraphQLConfig(filePath) {
27
- return graphqlConfig.loadConfigSync({
27
+ const rootDir = path.dirname(filePath);
28
+ const config = graphqlConfig.loadConfigSync({
28
29
  // load config relative to the file being linted
29
- rootDir: filePath ? path.dirname(filePath) : undefined,
30
+ rootDir,
30
31
  throwOnEmpty: false,
31
32
  throwOnMissing: false,
32
- extensions: [addCodeFileLoaderExtension],
33
+ });
34
+ if (!config) {
35
+ return null;
36
+ }
37
+ const project = config.getProjectForFile(filePath);
38
+ return graphqlConfig.loadConfigSync({
39
+ rootDir,
40
+ extensions: [codeFileLoaderExtension(project.extensions.pluckConfig)],
33
41
  });
34
42
  }
35
- function loadGraphQLConfig(options = {}) {
43
+ function loadGraphQLConfig(options) {
44
+ var _a;
36
45
  // We don't want cache config on test environment
37
46
  // Otherwise schema and documents will be same for all tests
38
47
  if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
@@ -57,53 +66,56 @@ function loadGraphQLConfig(options = {}) {
57
66
  new graphqlConfig.GraphQLConfig({
58
67
  config: configOptions,
59
68
  filepath: 'virtual-config',
60
- }, [addCodeFileLoaderExtension]);
69
+ }, [codeFileLoaderExtension((_a = options.extensions) === null || _a === void 0 ? void 0 : _a.pluckConfig)]);
61
70
  return graphQLConfig;
62
71
  }
63
- const addCodeFileLoaderExtension = api => {
64
- api.loaders.schema.register(new codeFileLoader.CodeFileLoader());
65
- api.loaders.documents.register(new codeFileLoader.CodeFileLoader());
72
+ const codeFileLoaderExtension = (pluckConfig) => api => {
73
+ const { schema, documents } = api.loaders;
74
+ schema.register(new codeFileLoader.CodeFileLoader({ pluckConfig }));
75
+ documents.register(new codeFileLoader.CodeFileLoader({ pluckConfig }));
66
76
  return { name: 'graphql-eslint-loaders' };
67
77
  };
68
78
 
69
79
  const blocksMap = new Map();
70
80
  let onDiskConfig;
81
+ let pluckConfig;
82
+ let RELEVANT_KEYWORDS;
71
83
  const processor = {
72
84
  supportsAutofix: true,
73
85
  preprocess(code, filePath) {
74
- var _a, _b, _c;
75
- onDiskConfig || (onDiskConfig = loadOnDiskGraphQLConfig(filePath));
76
- const graphQLTagPluckOptions = (_c = (_b = (_a = onDiskConfig === null || onDiskConfig === void 0 ? void 0 : onDiskConfig.getProjectForFile) === null || _a === void 0 ? void 0 : _a.call(onDiskConfig, filePath)) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c.graphqlTagPluck;
77
- const { modules = [], globalGqlIdentifierName = ['gql', 'graphql'], gqlMagicComment = 'GraphQL', } = graphQLTagPluckOptions || {};
78
- const RELEVANT_KEYWORDS = [
79
- ...new Set([
80
- ...modules.map(({ identifier }) => identifier),
81
- ...utils.asArray(globalGqlIdentifierName),
86
+ if (!pluckConfig) {
87
+ onDiskConfig = loadOnDiskGraphQLConfig(filePath);
88
+ const { modules = [], globalGqlIdentifierName = ['gql', 'graphql'], gqlMagicComment = 'GraphQL', } = (onDiskConfig === null || onDiskConfig === void 0 ? void 0 : onDiskConfig.getProjectForFile(filePath).extensions.pluckConfig) || {};
89
+ pluckConfig = {
90
+ skipIndent: true,
91
+ modules,
92
+ globalGqlIdentifierName,
82
93
  gqlMagicComment,
83
- ].filter(Boolean)),
84
- ];
94
+ };
95
+ RELEVANT_KEYWORDS = [
96
+ ...new Set([
97
+ ...modules.map(({ identifier }) => identifier),
98
+ ...utils.asArray(globalGqlIdentifierName),
99
+ gqlMagicComment,
100
+ ].filter(Boolean)),
101
+ ];
102
+ }
85
103
  if (RELEVANT_KEYWORDS.every(keyword => !code.includes(keyword))) {
86
104
  return [code];
87
105
  }
88
106
  try {
89
- const extractedDocuments = graphqlTagPluck.parseCode({
90
- code,
91
- filePath,
92
- options: {
93
- skipIndent: true,
94
- ...graphQLTagPluckOptions,
95
- },
96
- });
97
- const blocks = extractedDocuments.map(item => ({
107
+ const sources = graphqlTagPluck.gqlPluckFromCodeStringSync(filePath, code, pluckConfig);
108
+ const blocks = sources.map(item => ({
98
109
  filename: 'document.graphql',
99
- text: item.content,
100
- lineOffset: item.loc.start.line - 1,
101
- offset: item.start + 1,
110
+ text: item.body,
111
+ lineOffset: item.locationOffset.line - 1,
112
+ // @ts-expect-error -- `index` field exist but show ts error
113
+ offset: item.locationOffset.index + 1,
102
114
  }));
103
115
  blocksMap.set(filePath, blocks);
104
116
  return [...blocks, code /* source code must be provided and be last */];
105
117
  }
106
- catch (_d) {
118
+ catch (_a) {
107
119
  // in case of parsing error return code as is
108
120
  return [code];
109
121
  }
@@ -1212,32 +1224,6 @@ const rule$3 = {
1212
1224
  fullName
1213
1225
  }
1214
1226
  }
1215
- `,
1216
- },
1217
- {
1218
- title: 'Correct',
1219
- usage: [{ fragment: { style: 'kebab-case', suffix: 'Mutation', prefix: 'mutation.' } }],
1220
- name: 'mutation.add-alert.graphql',
1221
- code: /* GraphQL */ `
1222
- # mutation.add-alert.graphql
1223
- mutation addAlert($input: AddAlertInput!) {
1224
- addAlert(input: $input) {
1225
- ...AlertFields
1226
- }
1227
- }
1228
- `,
1229
- },
1230
- {
1231
- title: 'Correct',
1232
- usage: [{ fragment: { prefix: 'query.' } }],
1233
- name: 'query.me.graphql',
1234
- code: /* GraphQL */ `
1235
- # query.me.graphql
1236
- query me {
1237
- me {
1238
- ...UserFields
1239
- }
1240
- }
1241
1227
  `,
1242
1228
  },
1243
1229
  ],
@@ -1267,7 +1253,6 @@ const rule$3 = {
1267
1253
  properties: {
1268
1254
  style: { enum: CASE_STYLES },
1269
1255
  suffix: { type: 'string' },
1270
- prefix: { type: 'string' },
1271
1256
  },
1272
1257
  },
1273
1258
  },
@@ -1333,13 +1318,13 @@ const rule$3 = {
1333
1318
  option = { style: option };
1334
1319
  }
1335
1320
  const expectedExtension = options.fileExtension || fileExtension;
1336
- let expectedFilename = option.prefix || '';
1321
+ let expectedFilename;
1337
1322
  if (option.style) {
1338
1323
  expectedFilename =
1339
1324
  option.style === 'matchDocumentStyle' ? docName : convertCase(option.style, docName);
1340
1325
  }
1341
1326
  else {
1342
- expectedFilename += filename;
1327
+ expectedFilename = filename;
1343
1328
  }
1344
1329
  expectedFilename += (option.suffix || '') + expectedExtension;
1345
1330
  const filenameWithExtension = filename + expectedExtension;
@@ -4468,10 +4453,10 @@ function getSiblingOperations(projectForFile) {
4468
4453
 
4469
4454
  const debug$3 = debugFactory('graphql-eslint:parser');
4470
4455
  debug$3('cwd %o', process.cwd());
4471
- function parseForESLint(code, options = {}) {
4456
+ function parseForESLint(code, options) {
4472
4457
  try {
4473
- const filePath = options.filePath || '';
4474
- const realFilepath = filePath && getOnDiskFilepath(filePath);
4458
+ const { filePath } = options;
4459
+ const realFilepath = getOnDiskFilepath(filePath);
4475
4460
  const gqlConfig = loadGraphQLConfig(options);
4476
4461
  const projectForFile = realFilepath
4477
4462
  ? gqlConfig.getProjectForFile(realFilepath)
package/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { parseCode } from '@graphql-tools/graphql-tag-pluck';
1
+ import { gqlPluckFromCodeStringSync } from '@graphql-tools/graphql-tag-pluck';
2
2
  import { asArray, getDocumentNodeFromSchema, parseGraphQLSDL } from '@graphql-tools/utils';
3
3
  import { dirname, extname, basename, relative, resolve } from 'path';
4
4
  import debugFactory from 'debug';
5
- import { loadConfigSync, GraphQLConfig } from 'graphql-config';
5
+ import { GraphQLConfig, loadConfigSync } from 'graphql-config';
6
6
  import { CodeFileLoader } from '@graphql-tools/code-file-loader';
7
7
  import { Kind, visit, validate, TokenKind, isScalarType, DirectiveLocation, isInterfaceType, TypeInfo, visitWithTypeInfo, isObjectType as isObjectType$1, Source, isNonNullType, isListType, GraphQLObjectType, GraphQLInterfaceType, GraphQLSchema, GraphQLError } from 'graphql';
8
8
  import { validateSDL } from 'graphql/validation/validate';
@@ -18,15 +18,24 @@ import { codeFrameColumns } from '@babel/code-frame';
18
18
  const debug = debugFactory('graphql-eslint:graphql-config');
19
19
  let graphQLConfig;
20
20
  function loadOnDiskGraphQLConfig(filePath) {
21
- return loadConfigSync({
21
+ const rootDir = dirname(filePath);
22
+ const config = loadConfigSync({
22
23
  // load config relative to the file being linted
23
- rootDir: filePath ? dirname(filePath) : undefined,
24
+ rootDir,
24
25
  throwOnEmpty: false,
25
26
  throwOnMissing: false,
26
- extensions: [addCodeFileLoaderExtension],
27
+ });
28
+ if (!config) {
29
+ return null;
30
+ }
31
+ const project = config.getProjectForFile(filePath);
32
+ return loadConfigSync({
33
+ rootDir,
34
+ extensions: [codeFileLoaderExtension(project.extensions.pluckConfig)],
27
35
  });
28
36
  }
29
- function loadGraphQLConfig(options = {}) {
37
+ function loadGraphQLConfig(options) {
38
+ var _a;
30
39
  // We don't want cache config on test environment
31
40
  // Otherwise schema and documents will be same for all tests
32
41
  if (process.env.NODE_ENV !== 'test' && graphQLConfig) {
@@ -51,53 +60,56 @@ function loadGraphQLConfig(options = {}) {
51
60
  new GraphQLConfig({
52
61
  config: configOptions,
53
62
  filepath: 'virtual-config',
54
- }, [addCodeFileLoaderExtension]);
63
+ }, [codeFileLoaderExtension((_a = options.extensions) === null || _a === void 0 ? void 0 : _a.pluckConfig)]);
55
64
  return graphQLConfig;
56
65
  }
57
- const addCodeFileLoaderExtension = api => {
58
- api.loaders.schema.register(new CodeFileLoader());
59
- api.loaders.documents.register(new CodeFileLoader());
66
+ const codeFileLoaderExtension = (pluckConfig) => api => {
67
+ const { schema, documents } = api.loaders;
68
+ schema.register(new CodeFileLoader({ pluckConfig }));
69
+ documents.register(new CodeFileLoader({ pluckConfig }));
60
70
  return { name: 'graphql-eslint-loaders' };
61
71
  };
62
72
 
63
73
  const blocksMap = new Map();
64
74
  let onDiskConfig;
75
+ let pluckConfig;
76
+ let RELEVANT_KEYWORDS;
65
77
  const processor = {
66
78
  supportsAutofix: true,
67
79
  preprocess(code, filePath) {
68
- var _a, _b, _c;
69
- onDiskConfig || (onDiskConfig = loadOnDiskGraphQLConfig(filePath));
70
- const graphQLTagPluckOptions = (_c = (_b = (_a = onDiskConfig === null || onDiskConfig === void 0 ? void 0 : onDiskConfig.getProjectForFile) === null || _a === void 0 ? void 0 : _a.call(onDiskConfig, filePath)) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c.graphqlTagPluck;
71
- const { modules = [], globalGqlIdentifierName = ['gql', 'graphql'], gqlMagicComment = 'GraphQL', } = graphQLTagPluckOptions || {};
72
- const RELEVANT_KEYWORDS = [
73
- ...new Set([
74
- ...modules.map(({ identifier }) => identifier),
75
- ...asArray(globalGqlIdentifierName),
80
+ if (!pluckConfig) {
81
+ onDiskConfig = loadOnDiskGraphQLConfig(filePath);
82
+ const { modules = [], globalGqlIdentifierName = ['gql', 'graphql'], gqlMagicComment = 'GraphQL', } = (onDiskConfig === null || onDiskConfig === void 0 ? void 0 : onDiskConfig.getProjectForFile(filePath).extensions.pluckConfig) || {};
83
+ pluckConfig = {
84
+ skipIndent: true,
85
+ modules,
86
+ globalGqlIdentifierName,
76
87
  gqlMagicComment,
77
- ].filter(Boolean)),
78
- ];
88
+ };
89
+ RELEVANT_KEYWORDS = [
90
+ ...new Set([
91
+ ...modules.map(({ identifier }) => identifier),
92
+ ...asArray(globalGqlIdentifierName),
93
+ gqlMagicComment,
94
+ ].filter(Boolean)),
95
+ ];
96
+ }
79
97
  if (RELEVANT_KEYWORDS.every(keyword => !code.includes(keyword))) {
80
98
  return [code];
81
99
  }
82
100
  try {
83
- const extractedDocuments = parseCode({
84
- code,
85
- filePath,
86
- options: {
87
- skipIndent: true,
88
- ...graphQLTagPluckOptions,
89
- },
90
- });
91
- const blocks = extractedDocuments.map(item => ({
101
+ const sources = gqlPluckFromCodeStringSync(filePath, code, pluckConfig);
102
+ const blocks = sources.map(item => ({
92
103
  filename: 'document.graphql',
93
- text: item.content,
94
- lineOffset: item.loc.start.line - 1,
95
- offset: item.start + 1,
104
+ text: item.body,
105
+ lineOffset: item.locationOffset.line - 1,
106
+ // @ts-expect-error -- `index` field exist but show ts error
107
+ offset: item.locationOffset.index + 1,
96
108
  }));
97
109
  blocksMap.set(filePath, blocks);
98
110
  return [...blocks, code /* source code must be provided and be last */];
99
111
  }
100
- catch (_d) {
112
+ catch (_a) {
101
113
  // in case of parsing error return code as is
102
114
  return [code];
103
115
  }
@@ -1206,32 +1218,6 @@ const rule$3 = {
1206
1218
  fullName
1207
1219
  }
1208
1220
  }
1209
- `,
1210
- },
1211
- {
1212
- title: 'Correct',
1213
- usage: [{ fragment: { style: 'kebab-case', suffix: 'Mutation', prefix: 'mutation.' } }],
1214
- name: 'mutation.add-alert.graphql',
1215
- code: /* GraphQL */ `
1216
- # mutation.add-alert.graphql
1217
- mutation addAlert($input: AddAlertInput!) {
1218
- addAlert(input: $input) {
1219
- ...AlertFields
1220
- }
1221
- }
1222
- `,
1223
- },
1224
- {
1225
- title: 'Correct',
1226
- usage: [{ fragment: { prefix: 'query.' } }],
1227
- name: 'query.me.graphql',
1228
- code: /* GraphQL */ `
1229
- # query.me.graphql
1230
- query me {
1231
- me {
1232
- ...UserFields
1233
- }
1234
- }
1235
1221
  `,
1236
1222
  },
1237
1223
  ],
@@ -1261,7 +1247,6 @@ const rule$3 = {
1261
1247
  properties: {
1262
1248
  style: { enum: CASE_STYLES },
1263
1249
  suffix: { type: 'string' },
1264
- prefix: { type: 'string' },
1265
1250
  },
1266
1251
  },
1267
1252
  },
@@ -1327,13 +1312,13 @@ const rule$3 = {
1327
1312
  option = { style: option };
1328
1313
  }
1329
1314
  const expectedExtension = options.fileExtension || fileExtension;
1330
- let expectedFilename = option.prefix || '';
1315
+ let expectedFilename;
1331
1316
  if (option.style) {
1332
1317
  expectedFilename =
1333
1318
  option.style === 'matchDocumentStyle' ? docName : convertCase(option.style, docName);
1334
1319
  }
1335
1320
  else {
1336
- expectedFilename += filename;
1321
+ expectedFilename = filename;
1337
1322
  }
1338
1323
  expectedFilename += (option.suffix || '') + expectedExtension;
1339
1324
  const filenameWithExtension = filename + expectedExtension;
@@ -4462,10 +4447,10 @@ function getSiblingOperations(projectForFile) {
4462
4447
 
4463
4448
  const debug$3 = debugFactory('graphql-eslint:parser');
4464
4449
  debug$3('cwd %o', process.cwd());
4465
- function parseForESLint(code, options = {}) {
4450
+ function parseForESLint(code, options) {
4466
4451
  try {
4467
- const filePath = options.filePath || '';
4468
- const realFilepath = filePath && getOnDiskFilepath(filePath);
4452
+ const { filePath } = options;
4453
+ const realFilepath = getOnDiskFilepath(filePath);
4469
4454
  const gqlConfig = loadGraphQLConfig(options);
4470
4455
  const projectForFile = realFilepath
4471
4456
  ? gqlConfig.getProjectForFile(realFilepath)
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@graphql-eslint/eslint-plugin",
3
- "version": "3.12.0-alpha-20220929103858-c00a837",
3
+ "version": "3.12.0-alpha-20221008232037-33da317",
4
4
  "description": "GraphQL plugin for ESLint",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
7
  "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
8
8
  },
9
9
  "dependencies": {
10
- "@babel/code-frame": "^7.16.7",
11
- "@graphql-tools/code-file-loader": "^7.2.14",
12
- "@graphql-tools/graphql-tag-pluck": "^7.2.6",
13
- "@graphql-tools/utils": "^8.6.9",
10
+ "@babel/code-frame": "^7.18.6",
11
+ "@graphql-tools/code-file-loader": "^7.3.6",
12
+ "@graphql-tools/graphql-tag-pluck": "^7.3.6",
13
+ "@graphql-tools/utils": "^8.12.0",
14
14
  "chalk": "^4.1.2",
15
15
  "debug": "^4.3.4",
16
- "fast-glob": "^3.2.11",
17
- "graphql-config": "^4.3.0",
16
+ "fast-glob": "^3.2.12",
17
+ "graphql-config": "^4.3.5",
18
18
  "graphql-depth-limit": "^1.1.0",
19
19
  "lodash.lowercase": "^4.3.0"
20
20
  },
package/parser.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import { GraphQLESLintParseResult, ParserOptions } from './types';
2
- export declare function parseForESLint(code: string, options?: ParserOptions): GraphQLESLintParseResult;
2
+ export declare function parseForESLint(code: string, options: ParserOptions): GraphQLESLintParseResult;
@@ -5,7 +5,6 @@ declare const ACCEPTED_EXTENSIONS: ['.gql', '.graphql'];
5
5
  declare type PropertySchema = {
6
6
  style?: CaseStyle;
7
7
  suffix?: string;
8
- prefix?: string;
9
8
  };
10
9
  export declare type MatchDocumentFilenameRuleConfig = {
11
10
  fileExtension?: typeof ACCEPTED_EXTENSIONS[number];
package/schema.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { GraphQLProjectConfig } from 'graphql-config';
2
2
  import type { ParserOptions, Schema } from './types';
3
- export declare function getSchema(projectForFile: GraphQLProjectConfig, options?: ParserOptions): Schema;
3
+ export declare function getSchema(projectForFile: GraphQLProjectConfig, options?: Omit<ParserOptions, 'filePath'>): Schema;
package/testkit.d.ts CHANGED
@@ -16,9 +16,9 @@ export declare type GraphQLInvalidTestCase<T> = GraphQLValidTestCase<T> & {
16
16
  export declare class GraphQLRuleTester extends RuleTester {
17
17
  config: {
18
18
  parser: string;
19
- parserOptions: ParserOptions;
19
+ parserOptions: Omit<ParserOptions, 'filePath'>;
20
20
  };
21
- constructor(parserOptions?: ParserOptions);
21
+ constructor(parserOptions?: Omit<ParserOptions, 'filePath'>);
22
22
  fromMockFile(path: string): string;
23
23
  runGraphQLTests<Options, WithTypeInfo extends boolean = false>(ruleId: string, rule: GraphQLESLintRule<Options, WithTypeInfo>, tests: {
24
24
  valid: (string | GraphQLValidTestCase<Options>)[];
package/types.d.ts CHANGED
@@ -22,7 +22,7 @@ export interface ParserOptions {
22
22
  };
23
23
  graphQLParserOptions?: Omit<GraphQLParseOptions, 'noLocation'>;
24
24
  skipGraphQLConfig?: boolean;
25
- filePath?: string;
25
+ filePath: string;
26
26
  }
27
27
  export declare type ParserServices = {
28
28
  schema: Schema;