Skip to content

Commit 63cecdd

Browse files
authored
Add code file loader when using graphql-config (#231)
* Add custom loaders when using graphql-config * 👌 only create loader instances once * add changeset
1 parent 7f7c657 commit 63cecdd

File tree

9 files changed

+104
-31
lines changed

9 files changed

+104
-31
lines changed

.changeset/tame-onions-wink.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-eslint/eslint-plugin': minor
3+
---
4+
5+
Added code file compatibility for graphql-config projects
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"processor": "@graphql-eslint/graphql",
3+
"overrides": [
4+
{
5+
"files": ["*.graphql"],
6+
"parser": "@graphql-eslint/eslint-plugin",
7+
"parserOptions": {
8+
"schema": "./**/schema.graphql"
9+
},
10+
"plugins": ["@graphql-eslint"],
11+
"rules": {
12+
"@graphql-eslint/require-id-when-available": "warn",
13+
"@graphql-eslint/no-anonymous-operations": "warn",
14+
"@graphql-eslint/no-operation-name-suffix": "error",
15+
"@graphql-eslint/validate-against-schema": "error"
16+
}
17+
}
18+
]
19+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: "./**/schema.graphql"
2+
documents: "./query.js"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@graphql-eslint/example-graphql-config--code-file",
3+
"private": true,
4+
"version": "0.0.1",
5+
"repository": "https://github.com/dotansimha/graphql-eslint",
6+
"author": "Dotan Simha <[email protected]>",
7+
"license": "MIT",
8+
"scripts": {
9+
"lint": "eslint --ext graphql,js ."
10+
},
11+
"dependencies": {
12+
"@graphql-eslint/eslint-plugin": "0.6.0",
13+
"eslint": "7.14.0",
14+
"graphql": "15.4.0",
15+
"graphql-tag": "^2.11.0",
16+
"typescript": "4.1.2"
17+
}
18+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import gql from 'graphql-tag'
2+
3+
const myQuery = gql`
4+
query {
5+
user {
6+
name
7+
}
8+
}
9+
`;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
type Query {
2+
user: User!
3+
}
4+
5+
type User {
6+
id: ID!
7+
name: String!
8+
}

packages/plugin/src/parser.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,27 @@ import { GraphQLError, TypeInfo } from 'graphql';
44
import { Linter } from 'eslint';
55
import { GraphQLESLintParseResult, ParserOptions } from './types';
66
import { extractTokens } from './utils';
7-
import { getSchema } from './schema';
8-
import { getSiblingOperations } from './sibling-operations';
9-
import { loadConfigSync, GraphQLConfig } from 'graphql-config';
7+
import { getSchema, schemaLoaders } from './schema';
8+
import { getSiblingOperations, operationsLoaders } from './sibling-operations';
9+
import { loadConfigSync, GraphQLConfig, GraphQLExtensionDeclaration } from 'graphql-config';
1010

1111
export function parse(code: string, options?: ParserOptions): Linter.ESLintParseResult['ast'] {
1212
return parseForESLint(code, options).ast;
1313
}
1414

15+
const addCodeFileLoaderExtension: GraphQLExtensionDeclaration = (api) => {
16+
schemaLoaders.forEach(loader => api.loaders.schema.register(loader))
17+
operationsLoaders.forEach(loader => api.loaders.documents.register(loader))
18+
return { name: 'graphql-eslint-loaders' }
19+
}
20+
1521
export function parseForESLint(code: string, options?: ParserOptions): GraphQLESLintParseResult {
1622
const gqlConfig: GraphQLConfig | null = options?.skipGraphQLConfig
1723
? null
1824
: loadConfigSync({
1925
throwOnEmpty: false,
2026
throwOnMissing: false,
27+
extensions: [addCodeFileLoaderExtension]
2128
});
2229

2330
const schema = getSchema(options, gqlConfig);

packages/plugin/src/schema.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,29 @@ import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
22
import { JsonFileLoader } from '@graphql-tools/json-file-loader';
33
import { loadSchemaSync } from '@graphql-tools/load';
44
import { UrlLoader } from '@graphql-tools/url-loader';
5+
import { Loader, SingleFileOptions } from '@graphql-tools/utils';
56
import { buildSchema, GraphQLSchema } from 'graphql';
67
import { GraphQLConfig } from 'graphql-config';
78
import { dirname } from 'path';
89
import { ParserOptions } from './types';
910

1011
const schemaCache: Map<string, GraphQLSchema> = new Map();
1112

13+
export const schemaLoaders: Loader<string, SingleFileOptions>[] = [
14+
{
15+
loaderId: () => 'direct-string',
16+
canLoad: async () => false,
17+
load: async () => null,
18+
canLoadSync: pointer => typeof pointer === 'string' && pointer.includes('type '),
19+
loadSync: pointer => ({
20+
schema: buildSchema(pointer),
21+
}),
22+
},
23+
new GraphQLFileLoader(),
24+
new JsonFileLoader(),
25+
new UrlLoader(),
26+
]
27+
1228
export function getSchema(options: ParserOptions, gqlConfig: GraphQLConfig): GraphQLSchema | null {
1329
let schema: GraphQLSchema | null = null;
1430

@@ -44,20 +60,7 @@ export function getSchema(options: ParserOptions, gqlConfig: GraphQLConfig): Gra
4460
schema = loadSchemaSync(options.schema, {
4561
...(options.schemaOptions || {}),
4662
assumeValidSDL: true,
47-
loaders: [
48-
{
49-
loaderId: () => 'direct-string',
50-
canLoad: async () => false,
51-
load: async () => null,
52-
canLoadSync: pointer => typeof pointer === 'string' && pointer.includes('type '),
53-
loadSync: pointer => ({
54-
schema: buildSchema(pointer),
55-
}),
56-
},
57-
new GraphQLFileLoader(),
58-
new JsonFileLoader(),
59-
new UrlLoader(),
60-
],
63+
loaders: schemaLoaders,
6164
});
6265
schemaCache.set(schemaKey, schema);
6366
} catch (e) {

packages/plugin/src/sibling-operations.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
22
import { CodeFileLoader } from '@graphql-tools/code-file-loader';
33
import { loadDocumentsSync } from '@graphql-tools/load';
4-
import { Source } from '@graphql-tools/utils';
4+
import { Loader, SingleFileOptions, Source } from '@graphql-tools/utils';
55
import {
66
FragmentDefinitionNode,
77
FragmentSpreadNode,
@@ -18,6 +18,20 @@ import { dirname, join } from 'path';
1818
export type FragmentSource = { filePath: string; document: FragmentDefinitionNode };
1919
export type OperationSource = { filePath: string; document: OperationDefinitionNode };
2020

21+
export const operationsLoaders: Loader<string, SingleFileOptions>[] = [
22+
new GraphQLFileLoader(),
23+
new CodeFileLoader(),
24+
{
25+
loaderId: () => 'direct-string',
26+
canLoad: async () => false,
27+
load: async () => null,
28+
canLoadSync: pointer => typeof pointer === 'string' && pointer.includes('type '),
29+
loadSync: pointer => ({
30+
document: parse(pointer),
31+
}),
32+
},
33+
]
34+
2135
export type SiblingOperations = {
2236
available: boolean;
2337
getOperations(): OperationSource[];
@@ -35,19 +49,7 @@ export type SiblingOperations = {
3549
function loadSiblings(baseDir: string, loadPaths: string[]): Source[] {
3650
return loadDocumentsSync(loadPaths, {
3751
cwd: baseDir,
38-
loaders: [
39-
new GraphQLFileLoader(),
40-
new CodeFileLoader(),
41-
{
42-
loaderId: () => 'direct-string',
43-
canLoad: async () => false,
44-
load: async () => null,
45-
canLoadSync: pointer => typeof pointer === 'string' && pointer.includes('type '),
46-
loadSync: pointer => ({
47-
document: parse(pointer),
48-
}),
49-
},
50-
],
52+
loaders: operationsLoaders,
5153
}).map(r => ({ ...r, location: join(baseDir, r.location) }));
5254
}
5355

0 commit comments

Comments
 (0)