@khanacademy/graphql-flow 0.2.5 → 1.1.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 +1 -1
- package/.github/workflows/pr-checks.yml +13 -10
- package/CHANGELOG.md +35 -0
- package/Readme.md +41 -142
- 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 -67
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/run.js +42 -20
- package/dist/cli/run.js.flow +59 -23
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/schema.json +94 -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 +42 -22
- package/dist/generateTypeFiles.js.flow +84 -77
- 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 +21 -22
- package/dist/index.js.flow +32 -16
- package/dist/index.js.map +1 -1
- package/dist/parser/__test__/parse.test.js +247 -0
- package/dist/parser/parse.js +1 -1
- package/dist/parser/parse.js.flow +3 -1
- package/dist/parser/parse.js.map +1 -1
- package/dist/types.js.flow +30 -5
- package/flow-typed/npm/@babel/types_vx.x.x.js +17 -3
- package/package.json +4 -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 -67
- package/src/cli/run.js +59 -23
- package/src/cli/schema.json +94 -0
- package/src/enums.js +44 -15
- package/src/generateResponseType.js +55 -57
- package/src/generateTypeFiles.js +84 -77
- package/src/generateVariablesType.js +25 -28
- package/src/index.js +32 -16
- package/src/parser/parse.js +3 -1
- package/src/types.js +30 -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
|
@@ -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/dist/cli/config.js
CHANGED
|
@@ -3,45 +3,42 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.loadConfigFile = exports.getSchemas = void 0;
|
|
6
|
+
exports.validateOrThrow = exports.loadConfigFile = exports.getSchemas = exports.findApplicableConfig = void 0;
|
|
7
7
|
|
|
8
8
|
var _schemaFromIntrospectionData = require("../schemaFromIntrospectionData");
|
|
9
9
|
|
|
10
|
+
var _schema = _interopRequireDefault(require("./schema.json"));
|
|
11
|
+
|
|
10
12
|
var _fs = _interopRequireDefault(require("fs"));
|
|
11
13
|
|
|
12
14
|
var _graphql = require("graphql");
|
|
13
15
|
|
|
14
|
-
var
|
|
16
|
+
var _jsonschema = require("jsonschema");
|
|
15
17
|
|
|
16
18
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
const toplevelKeys = ['excludes', 'schemaFilePath', 'options', 'dumpOperations'];
|
|
24
|
-
Object.keys(data).forEach(k => {
|
|
25
|
-
if (!toplevelKeys.includes(k)) {
|
|
26
|
-
throw new Error(`Invalid attribute in config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(', ')}`);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
20
|
+
// eslint-disable-line flowtype-errors/uncovered
|
|
21
|
+
// eslint-disable-line flowtype-errors/uncovered
|
|
22
|
+
const validateOrThrow = (value, jsonSchema) => {
|
|
23
|
+
/* eslint-disable flowtype-errors/uncovered */
|
|
24
|
+
const result = (0, _jsonschema.validate)(value, jsonSchema);
|
|
29
25
|
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
Object.keys(data.options).forEach(k => {
|
|
33
|
-
if (!externalOptionsKeys.includes(k)) {
|
|
34
|
-
throw new Error(`Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(', ')}`);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
26
|
+
if (!result.valid) {
|
|
27
|
+
throw new Error(result.errors.map(error => error.toString()).join('\n'));
|
|
37
28
|
}
|
|
29
|
+
/* eslint-enable flowtype-errors/uncovered */
|
|
30
|
+
|
|
31
|
+
};
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
exports.validateOrThrow = validateOrThrow;
|
|
34
|
+
|
|
35
|
+
const loadConfigFile = configFile => {
|
|
36
|
+
// $FlowIgnore // eslint-disable-next-line flowtype-errors/uncovered
|
|
37
|
+
const data = require(configFile); // eslint-disable-next-line flowtype-errors/uncovered
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
validateOrThrow(data, _schema.default);
|
|
41
|
+
return data;
|
|
45
42
|
};
|
|
46
43
|
/**
|
|
47
44
|
* Loads a .json 'introspection query response', or a .graphql schema definition.
|
|
@@ -69,6 +66,34 @@ const getSchemas = schemaFilePath => {
|
|
|
69
66
|
return [schemaForValidation, schemaForTypeGeneration];
|
|
70
67
|
}
|
|
71
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* Find the first item of the `config.generate` array where both:
|
|
71
|
+
* - no item of `exclude` matches
|
|
72
|
+
* - at least one item of `match` matches
|
|
73
|
+
*/
|
|
74
|
+
|
|
72
75
|
|
|
73
76
|
exports.getSchemas = getSchemas;
|
|
77
|
+
|
|
78
|
+
const findApplicableConfig = (path, configs) => {
|
|
79
|
+
if (!Array.isArray(configs)) {
|
|
80
|
+
configs = [configs];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return configs.find(config => {
|
|
84
|
+
var _config$exclude;
|
|
85
|
+
|
|
86
|
+
if ((_config$exclude = config.exclude) !== null && _config$exclude !== void 0 && _config$exclude.some(exclude => new RegExp(exclude).test(path))) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!config.match) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return config.match.some(matcher => new RegExp(matcher).test(path));
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
exports.findApplicableConfig = findApplicableConfig;
|
|
74
99
|
//# sourceMappingURL=config.js.map
|
package/dist/cli/config.js.flow
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,76 +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.isAbsolute(data.schemaFilePath)
|
|
82
|
-
? data.schemaFilePath
|
|
83
|
-
: path.join(path.dirname(configFile), data.schemaFilePath),
|
|
84
|
-
dumpOperations: data.dumpOperations,
|
|
85
|
-
};
|
|
34
|
+
validateOrThrow(data, configSchema);
|
|
35
|
+
return data;
|
|
86
36
|
};
|
|
87
37
|
|
|
88
38
|
/**
|
|
@@ -110,3 +60,26 @@ export const getSchemas = (schemaFilePath: string): [GraphQLSchema, Schema] => {
|
|
|
110
60
|
return [schemaForValidation, schemaForTypeGeneration];
|
|
111
61
|
}
|
|
112
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/dist/cli/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/config.js"],"names":["
|
|
1
|
+
{"version":3,"sources":["../../src/cli/config.js"],"names":["validateOrThrow","value","jsonSchema","result","valid","Error","errors","map","error","toString","join","loadConfigFile","configFile","data","require","configSchema","getSchemas","schemaFilePath","raw","fs","readFileSync","endsWith","schemaForValidation","queryResponse","descriptions","schemaForTypeGeneration","introspectionData","JSON","parse","findApplicableConfig","path","configs","Array","isArray","find","config","exclude","some","RegExp","test","match","matcher"],"mappings":";;;;;;;AAIA;;AACA;;AAEA;;AACA;;AAQA;;;;AAX0C;AAWL;AAE9B,MAAMA,eAAe,GAAG,CAACC,KAAD,EAAeC,UAAf,KAAqC;AAChE;AACA,QAAMC,MAAM,GAAG,0BAASF,KAAT,EAAgBC,UAAhB,CAAf;;AACA,MAAI,CAACC,MAAM,CAACC,KAAZ,EAAmB;AACf,UAAM,IAAIC,KAAJ,CACFF,MAAM,CAACG,MAAP,CAAcC,GAAd,CAAmBC,KAAD,IAAWA,KAAK,CAACC,QAAN,EAA7B,EAA+CC,IAA/C,CAAoD,IAApD,CADE,CAAN;AAGH;AACD;;AACH,CATM;;;;AAWA,MAAMC,cAAc,GAAIC,UAAD,IAAgC;AAC1D;AACA,QAAMC,IAAY,GAAGC,OAAO,CAACF,UAAD,CAA5B,CAF0D,CAG1D;;;AACAZ,EAAAA,eAAe,CAACa,IAAD,EAAOE,eAAP,CAAf;AACA,SAAOF,IAAP;AACH,CANM;AAQP;AACA;AACA;;;;;AACO,MAAMG,UAAU,GAAIC,cAAD,IAAqD;AAC3E,QAAMC,GAAG,GAAGC,YAAGC,YAAH,CAAgBH,cAAhB,EAAgC,MAAhC,CAAZ;;AACA,MAAIA,cAAc,CAACI,QAAf,CAAwB,UAAxB,CAAJ,EAAyC;AACrC,UAAMC,mBAAmB,GAAG,0BAAYJ,GAAZ,CAA5B;AACA,UAAMK,aAAa,GAAG,0BAClBD,mBADkB,EAElB,oCAAsB;AAACE,MAAAA,YAAY,EAAE;AAAf,KAAtB,CAFkB,CAAtB;AAIA,UAAMC,uBAAuB,GAAG,+DAC5B;AACEF,IAAAA,aAAa,CAACV,IAFY,CAAhC;AAIA,WAAO,CAACS,mBAAD,EAAsBG,uBAAtB,CAAP;AACH,GAXD,MAWO;AACH;AACA,UAAMC,iBAAqC,GAAGC,IAAI,CAACC,KAAL,CAAWV,GAAX,CAA9C;AACA,UAAMI,mBAAmB,GAAG,gCAAkBI,iBAAlB,CAA5B;AACA,UAAMD,uBAAuB,GACzB,8DAA4BC,iBAA5B,CADJ;AAEA,WAAO,CAACJ,mBAAD,EAAsBG,uBAAtB,CAAP;AACH;AACJ,CArBM;AAuBP;AACA;AACA;AACA;AACA;;;;;AACO,MAAMI,oBAAoB,GAAG,CAChCC,IADgC,EAEhCC,OAFgC,KAGd;AAClB,MAAI,CAACC,KAAK,CAACC,OAAN,CAAcF,OAAd,CAAL,EAA6B;AACzBA,IAAAA,OAAO,GAAG,CAACA,OAAD,CAAV;AACH;;AACD,SAAOA,OAAO,CAACG,IAAR,CAAcC,MAAD,IAAY;AAAA;;AAC5B,2BAAIA,MAAM,CAACC,OAAX,4CAAI,gBAAgBC,IAAhB,CAAsBD,OAAD,IAAa,IAAIE,MAAJ,CAAWF,OAAX,EAAoBG,IAApB,CAAyBT,IAAzB,CAAlC,CAAJ,EAAuE;AACnE,aAAO,KAAP;AACH;;AACD,QAAI,CAACK,MAAM,CAACK,KAAZ,EAAmB;AACf,aAAO,IAAP;AACH;;AACD,WAAOL,MAAM,CAACK,KAAP,CAAaH,IAAb,CAAmBI,OAAD,IAAa,IAAIH,MAAJ,CAAWG,OAAX,EAAoBF,IAApB,CAAyBT,IAAzB,CAA/B,CAAP;AACH,GARM,CAAP;AASH,CAhBM","sourcesContent":["// @flow\nimport type {Schema} from '../types';\nimport type {GraphQLSchema} from 'graphql/type/schema';\n\nimport {schemaFromIntrospectionData} from '../schemaFromIntrospectionData';\nimport configSchema from './schema.json'; // eslint-disable-line flowtype-errors/uncovered\n\nimport fs from 'fs';\nimport {\n buildClientSchema,\n buildSchema,\n getIntrospectionQuery,\n graphqlSync,\n type IntrospectionQuery,\n} from 'graphql';\nimport type {Config, GenerateConfig} from '../types';\nimport {validate} from 'jsonschema'; // eslint-disable-line flowtype-errors/uncovered\n\nexport const validateOrThrow = (value: mixed, jsonSchema: mixed) => {\n /* eslint-disable flowtype-errors/uncovered */\n const result = validate(value, jsonSchema);\n if (!result.valid) {\n throw new Error(\n result.errors.map((error) => error.toString()).join('\\n'),\n );\n }\n /* eslint-enable flowtype-errors/uncovered */\n};\n\nexport const loadConfigFile = (configFile: string): Config => {\n // $FlowIgnore // eslint-disable-next-line flowtype-errors/uncovered\n const data: Config = require(configFile);\n // eslint-disable-next-line flowtype-errors/uncovered\n validateOrThrow(data, configSchema);\n return data;\n};\n\n/**\n * Loads a .json 'introspection query response', or a .graphql schema definition.\n */\nexport const getSchemas = (schemaFilePath: string): [GraphQLSchema, Schema] => {\n const raw = fs.readFileSync(schemaFilePath, 'utf8');\n if (schemaFilePath.endsWith('.graphql')) {\n const schemaForValidation = buildSchema(raw);\n const queryResponse = graphqlSync(\n schemaForValidation,\n getIntrospectionQuery({descriptions: true}),\n );\n const schemaForTypeGeneration = schemaFromIntrospectionData(\n // eslint-disable-next-line flowtype-errors/uncovered\n ((queryResponse.data: any): IntrospectionQuery),\n );\n return [schemaForValidation, schemaForTypeGeneration];\n } else {\n // eslint-disable-next-line flowtype-errors/uncovered\n const introspectionData: IntrospectionQuery = JSON.parse(raw);\n const schemaForValidation = buildClientSchema(introspectionData);\n const schemaForTypeGeneration =\n schemaFromIntrospectionData(introspectionData);\n return [schemaForValidation, schemaForTypeGeneration];\n }\n};\n\n/**\n * Find the first item of the `config.generate` array where both:\n * - no item of `exclude` matches\n * - at least one item of `match` matches\n */\nexport const findApplicableConfig = (\n path: string,\n configs: Array<GenerateConfig> | GenerateConfig,\n): ?GenerateConfig => {\n if (!Array.isArray(configs)) {\n configs = [configs];\n }\n return configs.find((config) => {\n if (config.exclude?.some((exclude) => new RegExp(exclude).test(path))) {\n return false;\n }\n if (!config.match) {\n return true;\n }\n return config.match.some((matcher) => new RegExp(matcher).test(path));\n });\n};\n"],"file":"config.js"}
|
package/dist/cli/run.js
CHANGED
|
@@ -31,7 +31,7 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* This CLI tool executes the following steps:
|
|
34
|
-
* 1)
|
|
34
|
+
* 1) parse & validate config file
|
|
35
35
|
* 2) crawl files to find all operations and fragments, with
|
|
36
36
|
* tagged template literals and expressions.
|
|
37
37
|
* 3) resolve the found operations, passing the literals and
|
|
@@ -42,25 +42,29 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
42
42
|
|
|
43
43
|
/** Step (1) */
|
|
44
44
|
const findGraphqlTagReferences = root => {
|
|
45
|
-
const response = (0, _child_process.execSync)("git grep -I --word-regexp --name-only --fixed-strings 'graphql-tag' -- '*.js' '*.jsx'", {
|
|
45
|
+
const response = (0, _child_process.execSync)("git grep -I --word-regexp --name-only --fixed-strings 'graphql-tag' -- '*.js' '*.jsx' '*.ts' '*.tsx'", {
|
|
46
46
|
encoding: 'utf8',
|
|
47
47
|
cwd: root
|
|
48
48
|
});
|
|
49
49
|
return response.trim().split('\n').map(relative => _path.default.join(root, relative));
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
const [_, __,
|
|
52
|
+
const [_, __, configFilePath, ...cliFiles] = process.argv;
|
|
53
53
|
|
|
54
|
-
if (
|
|
54
|
+
if (configFilePath === '-h' || configFilePath === '--help' || configFilePath === 'help' || !configFilePath) {
|
|
55
55
|
console.log(`graphql-flow
|
|
56
56
|
|
|
57
57
|
Usage: graphql-flow [configFile.json] [filesToCrawl...]`);
|
|
58
58
|
process.exit(1); // eslint-disable-line flowtype-errors/uncovered
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
const makeAbsPath = (maybeRelativePath, basePath) => {
|
|
62
|
+
return _path.default.isAbsolute(maybeRelativePath) ? maybeRelativePath : _path.default.join(basePath, maybeRelativePath);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const absConfigPath = makeAbsPath(configFilePath, process.cwd());
|
|
66
|
+
const config = (0, _config.loadConfigFile)(absConfigPath);
|
|
67
|
+
const inputFiles = cliFiles.length ? cliFiles : findGraphqlTagReferences(makeAbsPath(config.crawl.root, _path.default.dirname(absConfigPath)));
|
|
64
68
|
/** Step (2) */
|
|
65
69
|
|
|
66
70
|
const files = (0, _parse.processFiles)(inputFiles, f => {
|
|
@@ -110,22 +114,34 @@ if (errors.length) {
|
|
|
110
114
|
console.log(Object.keys(resolved).length, 'resolved queries');
|
|
111
115
|
/** Step (4) */
|
|
112
116
|
|
|
117
|
+
const schemaCache = {};
|
|
118
|
+
|
|
119
|
+
const getCachedSchemas = schemaFilePath => {
|
|
120
|
+
if (!schemaCache[schemaFilePath]) {
|
|
121
|
+
schemaCache[schemaFilePath] = (0, _config.getSchemas)(makeAbsPath(schemaFilePath, _path.default.dirname(absConfigPath)));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return schemaCache[schemaFilePath];
|
|
125
|
+
};
|
|
126
|
+
|
|
113
127
|
let validationFailures = 0;
|
|
114
128
|
const printedOperations = [];
|
|
115
|
-
Object.keys(resolved).forEach(
|
|
129
|
+
Object.keys(resolved).forEach(filePathAndLine => {
|
|
116
130
|
const {
|
|
117
131
|
document,
|
|
118
132
|
raw
|
|
119
|
-
} = resolved[
|
|
120
|
-
|
|
121
|
-
if (config.excludes.some(rx => rx.test(raw.loc.path))) {
|
|
122
|
-
return; // skip
|
|
123
|
-
}
|
|
124
|
-
|
|
133
|
+
} = resolved[filePathAndLine];
|
|
125
134
|
const hasNonFragments = document.definitions.some(({
|
|
126
135
|
kind
|
|
127
136
|
}) => kind !== 'FragmentDefinition');
|
|
128
|
-
const rawSource = raw.literals[0];
|
|
137
|
+
const rawSource = raw.literals[0];
|
|
138
|
+
const generateConfig = (0, _config.findApplicableConfig)( // strip off the trailing line number, e.g. `:23`
|
|
139
|
+
filePathAndLine.split(':')[0], config.generate);
|
|
140
|
+
|
|
141
|
+
if (!generateConfig) {
|
|
142
|
+
return; // no generate config matches, bail
|
|
143
|
+
} // eslint-disable-next-line flowtype-errors/uncovered
|
|
144
|
+
|
|
129
145
|
|
|
130
146
|
const withTypeNames = (0, _apolloUtilities.addTypenameToDocument)(document);
|
|
131
147
|
const printed = (0, _printer.print)(withTypeNames);
|
|
@@ -134,12 +150,18 @@ Object.keys(resolved).forEach(k => {
|
|
|
134
150
|
printedOperations.push(printed);
|
|
135
151
|
}
|
|
136
152
|
|
|
137
|
-
const
|
|
153
|
+
const pragmaResult = (0, _generateTypeFiles.processPragmas)(generateConfig, config.crawl, rawSource);
|
|
138
154
|
|
|
139
|
-
if (!
|
|
155
|
+
if (!pragmaResult.generate) {
|
|
140
156
|
return;
|
|
141
157
|
}
|
|
142
158
|
|
|
159
|
+
if (pragmaResult.strict != null) {
|
|
160
|
+
generateConfig.strictNullability = pragmaResult.strict;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const [schemaForValidation, schemaForTypeGeneration] = getCachedSchemas(generateConfig.schemaFilePath);
|
|
164
|
+
|
|
143
165
|
if (hasNonFragments) {
|
|
144
166
|
/* eslint-disable flowtype-errors/uncovered */
|
|
145
167
|
const errors = (0, _validation.validate)(schemaForValidation, withTypeNames);
|
|
@@ -158,7 +180,7 @@ Object.keys(resolved).forEach(k => {
|
|
|
158
180
|
}
|
|
159
181
|
|
|
160
182
|
try {
|
|
161
|
-
(0, _generateTypeFiles.generateTypeFiles)(raw.loc.path, schemaForTypeGeneration, withTypeNames,
|
|
183
|
+
(0, _generateTypeFiles.generateTypeFiles)(raw.loc.path, schemaForTypeGeneration, withTypeNames, generateConfig); // eslint-disable-next-line flowtype-errors/uncovered
|
|
162
184
|
} catch (err) {
|
|
163
185
|
console.error(`Error while generating operation from ${raw.loc.path}`);
|
|
164
186
|
console.error(printed); // eslint-disable-next-line flowtype-errors/uncovered
|
|
@@ -174,8 +196,8 @@ if (validationFailures) {
|
|
|
174
196
|
process.exit(1);
|
|
175
197
|
}
|
|
176
198
|
|
|
177
|
-
if (config.dumpOperations) {
|
|
178
|
-
const dumpOperations = config.dumpOperations;
|
|
199
|
+
if (config.crawl.dumpOperations) {
|
|
200
|
+
const dumpOperations = config.crawl.dumpOperations;
|
|
179
201
|
const parent = (0, _path.dirname)(dumpOperations);
|
|
180
202
|
(0, _fs.mkdirSync)(parent, {
|
|
181
203
|
recursive: true
|