@khanacademy/graphql-flow 0.2.4 → 1.0.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/.flowconfig +1 -0
- package/.github/workflows/changeset-release.yml +3 -17
- package/.github/workflows/pr-checks.yml +13 -10
- package/CHANGELOG.md +35 -0
- package/Readme.md +41 -132
- package/dist/__test__/example-schema.graphql +67 -0
- package/dist/__test__/generateTypeFileContents.test.js +157 -0
- package/dist/__test__/graphql-flow.test.js +639 -0
- package/dist/__test__/processPragmas.test.js +76 -0
- package/dist/cli/__test__/config.test.js +120 -0
- package/dist/cli/config.js +51 -26
- package/dist/cli/config.js.flow +40 -68
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/run.js +41 -19
- package/dist/cli/run.js.flow +58 -22
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/schema.json +91 -0
- package/dist/enums.js +20 -7
- package/dist/enums.js.flow +44 -15
- package/dist/enums.js.map +1 -1
- package/dist/generateResponseType.js +47 -47
- package/dist/generateResponseType.js.flow +55 -57
- package/dist/generateResponseType.js.map +1 -1
- package/dist/generateTypeFiles.js +41 -22
- package/dist/generateTypeFiles.js.flow +86 -78
- package/dist/generateTypeFiles.js.map +1 -1
- package/dist/generateVariablesType.js +24 -24
- package/dist/generateVariablesType.js.flow +25 -28
- package/dist/generateVariablesType.js.map +1 -1
- package/dist/index.js +18 -20
- package/dist/index.js.flow +31 -16
- package/dist/index.js.map +1 -1
- package/dist/parser/__test__/parse.test.js +247 -0
- package/dist/types.js.flow +28 -5
- package/flow-typed/npm/@babel/types_vx.x.x.js +17 -3
- package/package.json +3 -2
- package/src/__test__/generateTypeFileContents.test.js +55 -1
- package/src/__test__/graphql-flow.test.js +7 -7
- package/src/__test__/processPragmas.test.js +28 -15
- package/src/cli/__test__/config.test.js +120 -0
- package/src/cli/config.js +40 -68
- package/src/cli/run.js +58 -22
- package/src/cli/schema.json +91 -0
- package/src/enums.js +44 -15
- package/src/generateResponseType.js +55 -57
- package/src/generateTypeFiles.js +86 -78
- package/src/generateVariablesType.js +25 -28
- package/src/index.js +31 -16
- package/src/types.js +28 -5
- package/.github/actions/filter-files/action.yml +0 -37
- package/.github/actions/full-or-limited/action.yml +0 -27
- package/.github/actions/json-args/action.yml +0 -32
- package/.github/actions/setup/action.yml +0 -28
- package/dist/jest-mock-graphql-tag.js +0 -88
- package/dist/jest-mock-graphql-tag.js.flow +0 -96
- package/dist/jest-mock-graphql-tag.js.map +0 -1
- package/src/jest-mock-graphql-tag.js +0 -96
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
* Tests for our graphql flow generation!
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {DocumentNode} from 'graphql';
|
|
8
|
-
|
|
9
7
|
import {getSchemas} from '../cli/config';
|
|
10
8
|
import {documentToFlowTypes} from '..';
|
|
9
|
+
import gql from 'graphql-tag';
|
|
11
10
|
|
|
12
|
-
import type {
|
|
11
|
+
import type {GenerateConfig} from '../types';
|
|
13
12
|
|
|
14
13
|
// This allows us to "snapshot" a string cleanly.
|
|
15
14
|
/* eslint-disable flowtype-errors/uncovered */
|
|
@@ -21,12 +20,13 @@ expect.addSnapshotSerializer({
|
|
|
21
20
|
|
|
22
21
|
const [_, exampleSchema] = getSchemas(__dirname + '/example-schema.graphql');
|
|
23
22
|
|
|
24
|
-
const rawQueryToFlowTypes = (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
const rawQueryToFlowTypes = (
|
|
24
|
+
query: string,
|
|
25
|
+
options?: $Partial<GenerateConfig>,
|
|
26
|
+
): string => {
|
|
28
27
|
const node = gql(query);
|
|
29
28
|
return documentToFlowTypes(node, exampleSchema, {
|
|
29
|
+
schemaFilePath: '',
|
|
30
30
|
scalars: {PositiveNumber: 'number'},
|
|
31
31
|
...options,
|
|
32
32
|
})
|
|
@@ -1,63 +1,76 @@
|
|
|
1
1
|
// @flow
|
|
2
|
+
import type {CrawlConfig, GenerateConfig} from '../types';
|
|
3
|
+
|
|
2
4
|
import {processPragmas} from '../generateTypeFiles';
|
|
3
5
|
|
|
4
6
|
const pragma = '# @autogen\n';
|
|
5
7
|
const loosePragma = '# @autogen-loose\n';
|
|
6
8
|
|
|
9
|
+
const baseGenerate: GenerateConfig = {schemaFilePath: ''};
|
|
10
|
+
const baseCrawl: CrawlConfig = {root: ''};
|
|
11
|
+
|
|
7
12
|
describe('processPragmas', () => {
|
|
8
13
|
it('should work with no pragmas', () => {
|
|
9
|
-
expect(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
expect(
|
|
15
|
+
processPragmas(baseGenerate, baseCrawl, `query X { Y }`),
|
|
16
|
+
).toEqual({
|
|
17
|
+
generate: true,
|
|
18
|
+
strict: undefined,
|
|
13
19
|
});
|
|
14
20
|
});
|
|
15
21
|
|
|
16
22
|
it('should reject query without required pragma', () => {
|
|
17
|
-
expect(
|
|
23
|
+
expect(
|
|
24
|
+
processPragmas(
|
|
25
|
+
baseGenerate,
|
|
26
|
+
{...baseCrawl, pragma},
|
|
27
|
+
`query X { Y }`,
|
|
28
|
+
),
|
|
29
|
+
).toEqual({generate: false});
|
|
18
30
|
});
|
|
19
31
|
|
|
20
32
|
it('should accept query with required pragma', () => {
|
|
21
33
|
expect(
|
|
22
34
|
processPragmas(
|
|
23
|
-
|
|
35
|
+
baseGenerate,
|
|
36
|
+
{...baseCrawl, pragma},
|
|
24
37
|
`query X {
|
|
25
38
|
# @autogen
|
|
26
39
|
Y
|
|
27
40
|
}`,
|
|
28
41
|
),
|
|
29
42
|
).toEqual({
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
scalars: undefined,
|
|
43
|
+
strict: true,
|
|
44
|
+
generate: true,
|
|
33
45
|
});
|
|
34
46
|
});
|
|
35
47
|
|
|
36
48
|
it('should accept query with loose pragma', () => {
|
|
37
49
|
expect(
|
|
38
50
|
processPragmas(
|
|
39
|
-
|
|
51
|
+
baseGenerate,
|
|
52
|
+
{...baseCrawl, pragma, loosePragma},
|
|
40
53
|
`query X {
|
|
41
54
|
# @autogen-loose
|
|
42
55
|
Y
|
|
43
56
|
}`,
|
|
44
57
|
),
|
|
45
58
|
).toEqual({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
scalars: undefined,
|
|
59
|
+
strict: false,
|
|
60
|
+
generate: true,
|
|
49
61
|
});
|
|
50
62
|
});
|
|
51
63
|
|
|
52
64
|
it('should reject query with ignore pragma', () => {
|
|
53
65
|
expect(
|
|
54
66
|
processPragmas(
|
|
55
|
-
|
|
67
|
+
baseGenerate,
|
|
68
|
+
{...baseCrawl, ignorePragma: '# @ignore\n'},
|
|
56
69
|
`query X {
|
|
57
70
|
# @ignore
|
|
58
71
|
Y
|
|
59
72
|
}`,
|
|
60
73
|
),
|
|
61
|
-
).toEqual(
|
|
74
|
+
).toEqual({generate: false});
|
|
62
75
|
});
|
|
63
76
|
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import type {Config} from '../../types';
|
|
3
|
+
|
|
4
|
+
import {findApplicableConfig, validateOrThrow} from '../config';
|
|
5
|
+
import configSchema from '../schema.json'; // eslint-disable-line flowtype-errors/uncovered
|
|
6
|
+
|
|
7
|
+
describe('findApplicableConfig', () => {
|
|
8
|
+
it('should work with one that matches', () => {
|
|
9
|
+
const config = {
|
|
10
|
+
schemaFilePath: 'ok.graphql',
|
|
11
|
+
};
|
|
12
|
+
expect(findApplicableConfig('/hello', config)).toBe(config);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should be falsy if nothing matches', () => {
|
|
16
|
+
const config = {
|
|
17
|
+
schemaFilePath: 'ok.graphql',
|
|
18
|
+
exclude: [/hello$/],
|
|
19
|
+
};
|
|
20
|
+
expect(findApplicableConfig('/hello', config)).toBeUndefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should match & exclude with multiple configs', () => {
|
|
24
|
+
const configs = [
|
|
25
|
+
{schemaFilePath: 'one', match: [/\.jsx$/], exclude: [/^test/]},
|
|
26
|
+
{schemaFilePath: 'two', exclude: [/^hello/]},
|
|
27
|
+
{schemaFilePath: 'three'},
|
|
28
|
+
];
|
|
29
|
+
expect(findApplicableConfig('hello.js', configs)).toBe(configs[2]);
|
|
30
|
+
expect(findApplicableConfig('goodbye.js', configs)).toBe(configs[1]);
|
|
31
|
+
expect(findApplicableConfig('hello.jsx', configs)).toBe(configs[0]);
|
|
32
|
+
expect(findApplicableConfig('test.jsx', configs)).toBe(configs[1]);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('jsonschema validation', () => {
|
|
37
|
+
it('should accept valid schema', () => {
|
|
38
|
+
const config: Config = {
|
|
39
|
+
crawl: {
|
|
40
|
+
root: '/here/we/crawl',
|
|
41
|
+
},
|
|
42
|
+
generate: {
|
|
43
|
+
match: [/\.fixture\.js$/],
|
|
44
|
+
exclude: [
|
|
45
|
+
'_test\\.js$',
|
|
46
|
+
'\\bcourse-editor-package\\b',
|
|
47
|
+
'\\.fixture\\.js$',
|
|
48
|
+
'\\b__flowtests__\\b',
|
|
49
|
+
'\\bcourse-editor\\b',
|
|
50
|
+
],
|
|
51
|
+
readOnlyArray: false,
|
|
52
|
+
regenerateCommand: 'make gqlflow',
|
|
53
|
+
scalars: {
|
|
54
|
+
JSONString: 'string',
|
|
55
|
+
KALocale: 'string',
|
|
56
|
+
NaiveDateTime: 'string',
|
|
57
|
+
},
|
|
58
|
+
splitTypes: true,
|
|
59
|
+
generatedDirectory: '__graphql-types__',
|
|
60
|
+
exportAllObjectTypes: true,
|
|
61
|
+
schemaFilePath: './composed_schema.graphql',
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
validateOrThrow(
|
|
65
|
+
config,
|
|
66
|
+
configSchema, // eslint-disable-line flowtype-errors/uncovered
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should accept a schema with multiple generate configs', () => {
|
|
71
|
+
const generate = {
|
|
72
|
+
match: [/\.fixture\.js$/],
|
|
73
|
+
exclude: [
|
|
74
|
+
'_test\\.js$',
|
|
75
|
+
'\\bcourse-editor-package\\b',
|
|
76
|
+
'\\.fixture\\.js$',
|
|
77
|
+
'\\b__flowtests__\\b',
|
|
78
|
+
'\\bcourse-editor\\b',
|
|
79
|
+
],
|
|
80
|
+
readOnlyArray: false,
|
|
81
|
+
regenerateCommand: 'make gqlflow',
|
|
82
|
+
scalars: {
|
|
83
|
+
JSONString: 'string',
|
|
84
|
+
KALocale: 'string',
|
|
85
|
+
NaiveDateTime: 'string',
|
|
86
|
+
},
|
|
87
|
+
splitTypes: true,
|
|
88
|
+
generatedDirectory: '__graphql-types__',
|
|
89
|
+
exportAllObjectTypes: true,
|
|
90
|
+
schemaFilePath: './composed_schema.graphql',
|
|
91
|
+
};
|
|
92
|
+
const config: Config = {
|
|
93
|
+
crawl: {
|
|
94
|
+
root: '/here/we/crawl',
|
|
95
|
+
},
|
|
96
|
+
generate: [
|
|
97
|
+
{...generate, match: [/^static/], exportAllObjectTypes: false},
|
|
98
|
+
generate,
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
validateOrThrow(
|
|
102
|
+
config,
|
|
103
|
+
configSchema, // eslint-disable-line flowtype-errors/uncovered
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should reject invalid schema', () => {
|
|
108
|
+
expect(() =>
|
|
109
|
+
validateOrThrow(
|
|
110
|
+
{schemaFilePath: 10, options: {extraOption: 'hello'}},
|
|
111
|
+
configSchema, // eslint-disable-line flowtype-errors/uncovered
|
|
112
|
+
),
|
|
113
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
114
|
+
"instance is not allowed to have the additional property \\"schemaFilePath\\"
|
|
115
|
+
instance is not allowed to have the additional property \\"options\\"
|
|
116
|
+
instance requires property \\"crawl\\"
|
|
117
|
+
instance requires property \\"generate\\""
|
|
118
|
+
`);
|
|
119
|
+
});
|
|
120
|
+
});
|
package/src/cli/config.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @flow
|
|
2
|
-
import type {ExternalOptions} from '../generateTypeFiles';
|
|
3
2
|
import type {Schema} from '../types';
|
|
4
3
|
import type {GraphQLSchema} from 'graphql/type/schema';
|
|
5
4
|
|
|
6
5
|
import {schemaFromIntrospectionData} from '../schemaFromIntrospectionData';
|
|
6
|
+
import configSchema from './schema.json'; // eslint-disable-line flowtype-errors/uncovered
|
|
7
7
|
|
|
8
8
|
import fs from 'fs';
|
|
9
9
|
import {
|
|
@@ -13,77 +13,26 @@ import {
|
|
|
13
13
|
graphqlSync,
|
|
14
14
|
type IntrospectionQuery,
|
|
15
15
|
} from 'graphql';
|
|
16
|
-
import
|
|
16
|
+
import type {Config, GenerateConfig} from '../types';
|
|
17
|
+
import {validate} from 'jsonschema'; // eslint-disable-line flowtype-errors/uncovered
|
|
17
18
|
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
* object.
|
|
28
|
-
*/
|
|
29
|
-
type JSONConfig = {
|
|
30
|
-
excludes?: Array<string>,
|
|
31
|
-
schemaFilePath: string,
|
|
32
|
-
options?: ExternalOptions,
|
|
33
|
-
dumpOperations?: string,
|
|
19
|
+
export const validateOrThrow = (value: mixed, jsonSchema: mixed) => {
|
|
20
|
+
/* eslint-disable flowtype-errors/uncovered */
|
|
21
|
+
const result = validate(value, jsonSchema);
|
|
22
|
+
if (!result.valid) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
result.errors.map((error) => error.toString()).join('\n'),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
/* eslint-enable flowtype-errors/uncovered */
|
|
34
28
|
};
|
|
35
29
|
|
|
36
|
-
export const loadConfigFile = (configFile: string):
|
|
30
|
+
export const loadConfigFile = (configFile: string): Config => {
|
|
31
|
+
// $FlowIgnore // eslint-disable-next-line flowtype-errors/uncovered
|
|
32
|
+
const data: Config = require(configFile);
|
|
37
33
|
// eslint-disable-next-line flowtype-errors/uncovered
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
'excludes',
|
|
41
|
-
'schemaFilePath',
|
|
42
|
-
'options',
|
|
43
|
-
'dumpOperations',
|
|
44
|
-
];
|
|
45
|
-
Object.keys(data).forEach((k) => {
|
|
46
|
-
if (!toplevelKeys.includes(k)) {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`Invalid attribute in config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(
|
|
49
|
-
', ',
|
|
50
|
-
)}`,
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
if (data.options) {
|
|
55
|
-
const externalOptionsKeys = [
|
|
56
|
-
'pragma',
|
|
57
|
-
'loosePragma',
|
|
58
|
-
'ignorePragma',
|
|
59
|
-
'scalars',
|
|
60
|
-
'strictNullability',
|
|
61
|
-
'regenerateCommand',
|
|
62
|
-
'readOnlyArray',
|
|
63
|
-
'splitTypes',
|
|
64
|
-
'generatedDirectory',
|
|
65
|
-
'exportAllObjectTypes',
|
|
66
|
-
'typeFileName',
|
|
67
|
-
];
|
|
68
|
-
Object.keys(data.options).forEach((k) => {
|
|
69
|
-
if (!externalOptionsKeys.includes(k)) {
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(
|
|
72
|
-
', ',
|
|
73
|
-
)}`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
return {
|
|
79
|
-
options: data.options ?? {},
|
|
80
|
-
excludes: data.excludes?.map((string) => new RegExp(string)) ?? [],
|
|
81
|
-
schemaFilePath: path.join(
|
|
82
|
-
path.dirname(configFile),
|
|
83
|
-
data.schemaFilePath,
|
|
84
|
-
),
|
|
85
|
-
dumpOperations: data.dumpOperations,
|
|
86
|
-
};
|
|
34
|
+
validateOrThrow(data, configSchema);
|
|
35
|
+
return data;
|
|
87
36
|
};
|
|
88
37
|
|
|
89
38
|
/**
|
|
@@ -111,3 +60,26 @@ export const getSchemas = (schemaFilePath: string): [GraphQLSchema, Schema] => {
|
|
|
111
60
|
return [schemaForValidation, schemaForTypeGeneration];
|
|
112
61
|
}
|
|
113
62
|
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Find the first item of the `config.generate` array where both:
|
|
66
|
+
* - no item of `exclude` matches
|
|
67
|
+
* - at least one item of `match` matches
|
|
68
|
+
*/
|
|
69
|
+
export const findApplicableConfig = (
|
|
70
|
+
path: string,
|
|
71
|
+
configs: Array<GenerateConfig> | GenerateConfig,
|
|
72
|
+
): ?GenerateConfig => {
|
|
73
|
+
if (!Array.isArray(configs)) {
|
|
74
|
+
configs = [configs];
|
|
75
|
+
}
|
|
76
|
+
return configs.find((config) => {
|
|
77
|
+
if (config.exclude?.some((exclude) => new RegExp(exclude).test(path))) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
if (!config.match) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return config.match.some((matcher) => new RegExp(matcher).test(path));
|
|
84
|
+
});
|
|
85
|
+
};
|
package/src/cli/run.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import {generateTypeFiles, processPragmas} from '../generateTypeFiles';
|
|
5
5
|
import {processFiles} from '../parser/parse';
|
|
6
6
|
import {resolveDocuments} from '../parser/resolve';
|
|
7
|
-
import {getSchemas, loadConfigFile} from './config';
|
|
7
|
+
import {findApplicableConfig, getSchemas, loadConfigFile} from './config';
|
|
8
8
|
|
|
9
9
|
import {addTypenameToDocument} from 'apollo-utilities'; // eslint-disable-line flowtype-errors/uncovered
|
|
10
10
|
|
|
@@ -15,10 +15,11 @@ import {print} from 'graphql/language/printer';
|
|
|
15
15
|
import {validate} from 'graphql/validation';
|
|
16
16
|
import path from 'path';
|
|
17
17
|
import {dirname} from 'path';
|
|
18
|
+
import type {GenerateConfig} from '../types';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* This CLI tool executes the following steps:
|
|
21
|
-
* 1)
|
|
22
|
+
* 1) parse & validate config file
|
|
22
23
|
* 2) crawl files to find all operations and fragments, with
|
|
23
24
|
* tagged template literals and expressions.
|
|
24
25
|
* 3) resolve the found operations, passing the literals and
|
|
@@ -43,13 +44,13 @@ const findGraphqlTagReferences = (root: string): Array<string> => {
|
|
|
43
44
|
.map((relative) => path.join(root, relative));
|
|
44
45
|
};
|
|
45
46
|
|
|
46
|
-
const [_, __,
|
|
47
|
+
const [_, __, configFilePath, ...cliFiles] = process.argv;
|
|
47
48
|
|
|
48
49
|
if (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
!
|
|
50
|
+
configFilePath === '-h' ||
|
|
51
|
+
configFilePath === '--help' ||
|
|
52
|
+
configFilePath === 'help' ||
|
|
53
|
+
!configFilePath
|
|
53
54
|
) {
|
|
54
55
|
console.log(`graphql-flow
|
|
55
56
|
|
|
@@ -57,15 +58,21 @@ Usage: graphql-flow [configFile.json] [filesToCrawl...]`);
|
|
|
57
58
|
process.exit(1); // eslint-disable-line flowtype-errors/uncovered
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
const
|
|
61
|
+
const makeAbsPath = (maybeRelativePath: string, basePath: string) => {
|
|
62
|
+
return path.isAbsolute(maybeRelativePath)
|
|
63
|
+
? maybeRelativePath
|
|
64
|
+
: path.join(basePath, maybeRelativePath);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const absConfigPath = makeAbsPath(configFilePath, process.cwd());
|
|
61
68
|
|
|
62
|
-
const
|
|
63
|
-
config.schemaFilePath,
|
|
64
|
-
);
|
|
69
|
+
const config = loadConfigFile(absConfigPath);
|
|
65
70
|
|
|
66
71
|
const inputFiles = cliFiles.length
|
|
67
72
|
? cliFiles
|
|
68
|
-
: findGraphqlTagReferences(
|
|
73
|
+
: findGraphqlTagReferences(
|
|
74
|
+
makeAbsPath(config.crawl.root, path.dirname(absConfigPath)),
|
|
75
|
+
);
|
|
69
76
|
|
|
70
77
|
/** Step (2) */
|
|
71
78
|
|
|
@@ -111,19 +118,37 @@ console.log(Object.keys(resolved).length, 'resolved queries');
|
|
|
111
118
|
|
|
112
119
|
/** Step (4) */
|
|
113
120
|
|
|
121
|
+
const schemaCache = {};
|
|
122
|
+
const getCachedSchemas = (schemaFilePath: string) => {
|
|
123
|
+
if (!schemaCache[schemaFilePath]) {
|
|
124
|
+
schemaCache[schemaFilePath] = getSchemas(
|
|
125
|
+
makeAbsPath(schemaFilePath, path.dirname(absConfigPath)),
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return schemaCache[schemaFilePath];
|
|
130
|
+
};
|
|
131
|
+
|
|
114
132
|
let validationFailures: number = 0;
|
|
115
133
|
const printedOperations: Array<string> = [];
|
|
116
134
|
|
|
117
|
-
Object.keys(resolved).forEach((
|
|
118
|
-
const {document, raw} = resolved[
|
|
119
|
-
|
|
120
|
-
return; // skip
|
|
121
|
-
}
|
|
135
|
+
Object.keys(resolved).forEach((filePathAndLine) => {
|
|
136
|
+
const {document, raw} = resolved[filePathAndLine];
|
|
137
|
+
|
|
122
138
|
const hasNonFragments = document.definitions.some(
|
|
123
139
|
({kind}) => kind !== 'FragmentDefinition',
|
|
124
140
|
);
|
|
125
141
|
const rawSource: string = raw.literals[0];
|
|
126
142
|
|
|
143
|
+
const generateConfig = findApplicableConfig(
|
|
144
|
+
// strip off the trailing line number, e.g. `:23`
|
|
145
|
+
filePathAndLine.split(':')[0],
|
|
146
|
+
config.generate,
|
|
147
|
+
);
|
|
148
|
+
if (!generateConfig) {
|
|
149
|
+
return; // no generate config matches, bail
|
|
150
|
+
}
|
|
151
|
+
|
|
127
152
|
// eslint-disable-next-line flowtype-errors/uncovered
|
|
128
153
|
const withTypeNames: DocumentNode = addTypenameToDocument(document);
|
|
129
154
|
const printed = print(withTypeNames);
|
|
@@ -131,10 +156,21 @@ Object.keys(resolved).forEach((k) => {
|
|
|
131
156
|
printedOperations.push(printed);
|
|
132
157
|
}
|
|
133
158
|
|
|
134
|
-
const
|
|
135
|
-
|
|
159
|
+
const pragmaResult = processPragmas(
|
|
160
|
+
generateConfig,
|
|
161
|
+
config.crawl,
|
|
162
|
+
rawSource,
|
|
163
|
+
);
|
|
164
|
+
if (!pragmaResult.generate) {
|
|
136
165
|
return;
|
|
137
166
|
}
|
|
167
|
+
if (pragmaResult.strict != null) {
|
|
168
|
+
generateConfig.strictNullability = pragmaResult.strict;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const [schemaForValidation, schemaForTypeGeneration] = getCachedSchemas(
|
|
172
|
+
generateConfig.schemaFilePath,
|
|
173
|
+
);
|
|
138
174
|
|
|
139
175
|
if (hasNonFragments) {
|
|
140
176
|
/* eslint-disable flowtype-errors/uncovered */
|
|
@@ -158,7 +194,7 @@ Object.keys(resolved).forEach((k) => {
|
|
|
158
194
|
raw.loc.path,
|
|
159
195
|
schemaForTypeGeneration,
|
|
160
196
|
withTypeNames,
|
|
161
|
-
|
|
197
|
+
generateConfig,
|
|
162
198
|
);
|
|
163
199
|
// eslint-disable-next-line flowtype-errors/uncovered
|
|
164
200
|
} catch (err) {
|
|
@@ -178,8 +214,8 @@ if (validationFailures) {
|
|
|
178
214
|
process.exit(1);
|
|
179
215
|
}
|
|
180
216
|
|
|
181
|
-
if (config.dumpOperations) {
|
|
182
|
-
const dumpOperations = config.dumpOperations;
|
|
217
|
+
if (config.crawl.dumpOperations) {
|
|
218
|
+
const dumpOperations = config.crawl.dumpOperations;
|
|
183
219
|
const parent = dirname(dumpOperations);
|
|
184
220
|
mkdirSync(parent, {recursive: true});
|
|
185
221
|
writeFileSync(
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema":"http://json-schema.org/draft-07/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"definitions": {
|
|
6
|
+
"GenerateConfig": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaFilePath": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
"match": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": {
|
|
16
|
+
"oneOf": [
|
|
17
|
+
{ "type": "object" },
|
|
18
|
+
{ "type": "string" }
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"exclude": {
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": {
|
|
25
|
+
"oneOf": [
|
|
26
|
+
{ "type": "object" },
|
|
27
|
+
{ "type": "string" }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"scalars": {
|
|
32
|
+
"type": "object"
|
|
33
|
+
},
|
|
34
|
+
"strictNullability": {
|
|
35
|
+
"type": "boolean"
|
|
36
|
+
},
|
|
37
|
+
"regenerateCommand": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"readOnlyArray": {
|
|
41
|
+
"type": "boolean"
|
|
42
|
+
},
|
|
43
|
+
"splitTypes": {
|
|
44
|
+
"type": "boolean"
|
|
45
|
+
},
|
|
46
|
+
"generatedDirectory": {
|
|
47
|
+
"type": "string"
|
|
48
|
+
},
|
|
49
|
+
"exportAllObjectTypes": {
|
|
50
|
+
"type": "boolean"
|
|
51
|
+
},
|
|
52
|
+
"typeFileName": {
|
|
53
|
+
"type": "string"
|
|
54
|
+
},
|
|
55
|
+
"experimentalEnums": {
|
|
56
|
+
"type": "boolean"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"required": [
|
|
60
|
+
"schemaFilePath"
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"properties": {
|
|
65
|
+
"crawl": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"properties": {
|
|
69
|
+
"root": {"type": "string"},
|
|
70
|
+
"pragma": {
|
|
71
|
+
"type": "string"
|
|
72
|
+
},
|
|
73
|
+
"loosePragma": {
|
|
74
|
+
"type": "string"
|
|
75
|
+
},
|
|
76
|
+
"ignorePragma": {
|
|
77
|
+
"type": "string"
|
|
78
|
+
},
|
|
79
|
+
"dumpOperations": {
|
|
80
|
+
"type": "string"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"required": [ "root" ]
|
|
84
|
+
},
|
|
85
|
+
"generate": {"oneOf": [
|
|
86
|
+
{"$ref": "#/definitions/GenerateConfig"},
|
|
87
|
+
{"type": "array", "items": {"$ref": "#/definitions/GenerateConfig"}}
|
|
88
|
+
]}
|
|
89
|
+
},
|
|
90
|
+
"required": [ "crawl", "generate" ]
|
|
91
|
+
}
|