@khanacademy/graphql-flow 0.2.3 → 0.3.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 +15 -10
- package/CHANGELOG.md +19 -0
- package/Readme.md +36 -1
- package/dist/cli/config.js +102 -15
- package/dist/cli/config.js.flow +131 -29
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/run.js +45 -11
- package/dist/cli/run.js.flow +45 -7
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/utils.js +21 -0
- package/dist/cli/utils.js.flow +14 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/enums.js +15 -2
- package/dist/enums.js.flow +38 -9
- package/dist/enums.js.map +1 -1
- package/dist/generateTypeFiles.js +30 -7
- package/dist/generateTypeFiles.js.flow +68 -38
- package/dist/generateTypeFiles.js.map +1 -1
- package/dist/index.js +18 -12
- package/dist/index.js.flow +27 -11
- package/dist/index.js.map +1 -1
- package/dist/types.js.flow +3 -0
- package/flow-typed/npm/@babel/types_vx.x.x.js +17 -3
- package/package.json +1 -1
- package/src/__test__/generateTypeFileContents.test.js +52 -0
- package/src/cli/__test__/config.test.js +94 -0
- package/src/cli/__test__/utils.test.js +19 -0
- package/src/cli/config.js +131 -29
- package/src/cli/run.js +45 -7
- package/src/cli/utils.js +14 -0
- package/src/enums.js +38 -9
- package/src/generateTypeFiles.js +68 -38
- package/src/index.js +27 -11
- package/src/types.js +3 -0
- 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/.flowconfig
CHANGED
|
@@ -34,7 +34,7 @@ jobs:
|
|
|
34
34
|
- uses: actions/checkout@v2
|
|
35
35
|
with:
|
|
36
36
|
fetch-depth: 0
|
|
37
|
-
- uses:
|
|
37
|
+
- uses: Khan/actions@shared-node-cache-v0.0.2
|
|
38
38
|
with:
|
|
39
39
|
node-version: 12.x
|
|
40
40
|
|
|
@@ -55,8 +55,8 @@ jobs:
|
|
|
55
55
|
if: steps.changesets.outputs.published == 'true'
|
|
56
56
|
uses: rtCamp/action-slack-notify@v2
|
|
57
57
|
env:
|
|
58
|
-
SLACK_WEBHOOK: ${{ secrets.
|
|
59
|
-
SLACK_CHANNEL:
|
|
58
|
+
SLACK_WEBHOOK: ${{ secrets.SLACK_FEI_FIREHOSE }}
|
|
59
|
+
SLACK_CHANNEL: fei-firehose
|
|
60
60
|
SLACK_MSG_AUTHOR: ${{ github.event.pull_request.user.login }}
|
|
61
61
|
SLACK_USERNAME: GithubGoose
|
|
62
62
|
SLACK_ICON_EMOJI: ":goose:"
|
|
@@ -64,17 +64,3 @@ jobs:
|
|
|
64
64
|
SLACK_TITLE: "New Graphql-Flow release!"
|
|
65
65
|
SLACK_FOOTER: Graphql-Flow Slack Notification
|
|
66
66
|
MSG_MINIMAL: true
|
|
67
|
-
|
|
68
|
-
- name: Send a Slack notification for mobile if a publish happens
|
|
69
|
-
if: steps.changesets.outputs.published == 'true'
|
|
70
|
-
uses: rtCamp/action-slack-notify@v2
|
|
71
|
-
env:
|
|
72
|
-
SLACK_WEBHOOK: ${{ secrets.SLACK_FEIMOBILE_WEBHOOK }}
|
|
73
|
-
SLACK_CHANNEL: frontend-infra-mobile
|
|
74
|
-
SLACK_MSG_AUTHOR: ${{ github.event.pull_request.user.login }}
|
|
75
|
-
SLACK_USERNAME: GithubGoose
|
|
76
|
-
SLACK_ICON_EMOJI: ":goose:"
|
|
77
|
-
SLACK_MESSAGE: "A new version of ${{ github.event.repository.name }} was published! 🎉 \nRelease notes → https://github.com/Khan/${{ github.event.repository.name }}/releases/"
|
|
78
|
-
SLACK_TITLE: "New Graphql-Flow release!"
|
|
79
|
-
SLACK_FOOTER: Graphql-Flow Slack Notification
|
|
80
|
-
MSG_MINIMAL: true
|
|
@@ -17,16 +17,21 @@ jobs:
|
|
|
17
17
|
node-version: [16.x]
|
|
18
18
|
steps:
|
|
19
19
|
- uses: actions/checkout@v2
|
|
20
|
-
- uses:
|
|
21
|
-
id: setup
|
|
20
|
+
- uses: Khan/actions@shared-node-cache-v0
|
|
22
21
|
with:
|
|
23
22
|
node-version: ${{ matrix.node-version }}
|
|
24
23
|
|
|
24
|
+
- name: Get All Changed Files
|
|
25
|
+
uses: jaredly/get-changed-files@absolute
|
|
26
|
+
id: changed
|
|
27
|
+
with:
|
|
28
|
+
format: 'json'
|
|
29
|
+
|
|
25
30
|
- id: js-files
|
|
26
31
|
name: Find .js changed files
|
|
27
|
-
uses:
|
|
32
|
+
uses: Khan/actions@filter-files-v0
|
|
28
33
|
with:
|
|
29
|
-
changed-files: ${{ steps.
|
|
34
|
+
changed-files: ${{ steps.changed.outputs.added_modified }}
|
|
30
35
|
extensions: '.js'
|
|
31
36
|
|
|
32
37
|
- name: Run Flow
|
|
@@ -34,14 +39,14 @@ jobs:
|
|
|
34
39
|
run: yarn flow
|
|
35
40
|
|
|
36
41
|
- id: eslint-reset
|
|
37
|
-
uses:
|
|
42
|
+
uses: Khan/actions@filter-files-v0
|
|
38
43
|
name: Files that would trigger a full eslint run
|
|
39
44
|
with:
|
|
40
|
-
changed-files: ${{ steps.
|
|
45
|
+
changed-files: ${{ steps.changed.outputs.added_modified }}
|
|
41
46
|
files: '.eslintrc.js,package.json,.eslintignore'
|
|
42
47
|
|
|
43
48
|
- name: Eslint
|
|
44
|
-
uses:
|
|
49
|
+
uses: Khan/actions@full-or-limited-v0
|
|
45
50
|
with:
|
|
46
51
|
full-trigger: ${{ steps.eslint-reset.outputs.filtered }}
|
|
47
52
|
full: yarn eslint
|
|
@@ -49,14 +54,14 @@ jobs:
|
|
|
49
54
|
limited: yarn eslint {}
|
|
50
55
|
|
|
51
56
|
- id: jest-reset
|
|
52
|
-
uses:
|
|
57
|
+
uses: Khan/actions@filter-files-v0
|
|
53
58
|
name: Files that would trigger a full jest run
|
|
54
59
|
with:
|
|
55
|
-
changed-files: ${{ steps.
|
|
60
|
+
changed-files: ${{ steps.changed.outputs.added_modified }}
|
|
56
61
|
files: 'package.json,package-lock.json'
|
|
57
62
|
|
|
58
63
|
- name: Jest
|
|
59
|
-
uses:
|
|
64
|
+
uses: Khan/actions@full-or-limited-v0
|
|
60
65
|
with:
|
|
61
66
|
full-trigger: ${{ steps.jest-reset.outputs.filtered }}
|
|
62
67
|
full: yarn jest
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @khanacademy/graphql-flow
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 093fa5f: Enable `experimentalEnums` in a config or subconfig file in to enable the export of flow enum types, which replace the default string union literals. The type currently comes with eslint decorators to skirt a bug in eslint and flow.
|
|
8
|
+
- 5078624: Users can add files with the name ending in `graphql-flow.config.js` with a subset of the config fields (`options`, `excludes`) in order to have more granular control of the behavior. Another field, `extends`, takes the path of another config file to use as a base and extends/overrides fields. If no `extends` is provided, the file completely overwrites any other config files (as far as `options` and `excludes`).
|
|
9
|
+
|
|
10
|
+
## 0.2.5
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 0df32ac: Allow generatedDir to be an absolute path
|
|
15
|
+
|
|
16
|
+
## 0.2.4
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 843839c: Add 'dumpOperations' config option, to enable safelisting
|
|
21
|
+
|
|
3
22
|
## 0.2.3
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/Readme.md
CHANGED
|
@@ -23,6 +23,26 @@ Write a config file, with the following options:
|
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
Optionally add subconfig files to subdirectories for granular control of behavior, with the following options:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
// Note that this file must be named, or end with, "graphql-flow.config.json"
|
|
31
|
+
// I.e., "my-service.graphql.config.json" would also work.
|
|
32
|
+
// These files will affect the directory in which they are located and all subdirectories, unless overridden by a deeper subconfig.
|
|
33
|
+
|
|
34
|
+
// Optionally add the path of another config file. Can be the root config (provided when running the script) or any other subconfig to merge options.
|
|
35
|
+
// If a chain of extends are provided, will resolve in order. Be sure not to extend in a circle-- currently, this will just cause a stack overflow error.
|
|
36
|
+
// Cannot currently override `schemaFilePath`.
|
|
37
|
+
"extends": "./another/config/from/root.config.json",
|
|
38
|
+
// Can extend or override `excludes` and `options`.
|
|
39
|
+
"excludes": ["\\bsome-thing", "_test.jsx?$"],
|
|
40
|
+
"options": {
|
|
41
|
+
...
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
26
46
|
Then run from the CLI, like so:
|
|
27
47
|
|
|
28
48
|
```bash
|
|
@@ -42,7 +62,17 @@ type Options = {
|
|
|
42
62
|
readOnlyArray: boolean = true,
|
|
43
63
|
scalars: {[key: string]: 'string' | 'boolean' | 'number'}
|
|
44
64
|
|
|
45
|
-
// Specify the name of the generated types directory
|
|
65
|
+
// Specify the name of the generated types directory. If this
|
|
66
|
+
// is a relative path, then this is used to suffix the output
|
|
67
|
+
// directory; if it's an absolute path it's used to prefix the
|
|
68
|
+
// output directory. For instance, if a gql directive is
|
|
69
|
+
// found in /foo/bar/baz/query.js and you run the cli (or
|
|
70
|
+
// jest) from directory /foo, then:
|
|
71
|
+
// * if `generatedDirectory` is "__generated__", the output will
|
|
72
|
+
// be in /foo/bar/baz/__generated__/index.js and sibling files
|
|
73
|
+
// * if `generatedDirectory` is "/tmp/__generated__", the output
|
|
74
|
+
// will be in /tmp/__generated__/bar/baz/index.js and sibling
|
|
75
|
+
// files.
|
|
46
76
|
generatedDirectory: string = '__generated__',
|
|
47
77
|
|
|
48
78
|
// The default generated type contains both the types of the response
|
|
@@ -74,6 +104,11 @@ type Options = {
|
|
|
74
104
|
// A template for the name of generated files
|
|
75
105
|
// default: [operationName].js
|
|
76
106
|
typeFileName?: string,
|
|
107
|
+
|
|
108
|
+
// Generate flow enums to replace literal unions in generated types. Exports
|
|
109
|
+
// each set of enums from each file regardless of other options. Designated
|
|
110
|
+
// "experimental" because of bug in eslint that requires config comments.
|
|
111
|
+
experimentalEnums?: boolean,
|
|
77
112
|
}
|
|
78
113
|
```
|
|
79
114
|
|
package/dist/cli/config.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.loadConfigFile = exports.getSchemas = void 0;
|
|
6
|
+
exports.loadSubConfigFile = exports.loadDirConfigFiles = exports.loadConfigFile = exports.getSchemas = void 0;
|
|
7
7
|
|
|
8
8
|
var _schemaFromIntrospectionData = require("../schemaFromIntrospectionData");
|
|
9
9
|
|
|
@@ -16,38 +16,114 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
16
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
17
|
|
|
18
18
|
const loadConfigFile = configFile => {
|
|
19
|
-
var _data$options, _data$excludes$map, _data$excludes;
|
|
19
|
+
var _data$options, _data$options2, _data$excludes$map, _data$excludes;
|
|
20
20
|
|
|
21
21
|
// eslint-disable-next-line flowtype-errors/uncovered
|
|
22
22
|
const data = JSON.parse(_fs.default.readFileSync(configFile, 'utf8'));
|
|
23
|
-
const toplevelKeys = ['excludes', 'schemaFilePath', 'options'];
|
|
23
|
+
const toplevelKeys = ['excludes', 'schemaFilePath', 'options', 'dumpOperations'];
|
|
24
24
|
Object.keys(data).forEach(k => {
|
|
25
25
|
if (!toplevelKeys.includes(k)) {
|
|
26
26
|
throw new Error(`Invalid attribute in config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(', ')}`);
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
|
+
validateOptions(configFile, (_data$options = data.options) !== null && _data$options !== void 0 ? _data$options : {});
|
|
30
|
+
return {
|
|
31
|
+
options: (_data$options2 = data.options) !== null && _data$options2 !== void 0 ? _data$options2 : {},
|
|
32
|
+
excludes: (_data$excludes$map = (_data$excludes = data.excludes) === null || _data$excludes === void 0 ? void 0 : _data$excludes.map(string => new RegExp(string))) !== null && _data$excludes$map !== void 0 ? _data$excludes$map : [],
|
|
33
|
+
schemaFilePath: _path.default.isAbsolute(data.schemaFilePath) ? data.schemaFilePath : _path.default.join(_path.default.dirname(configFile), data.schemaFilePath),
|
|
34
|
+
dumpOperations: data.dumpOperations
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Subdirectory config to extend or overwrite higher-level config.
|
|
39
|
+
* @param {string} extends - Path from root; optional field for a config file in a subdirectory. If left blank, config file will overwrite root for directory.
|
|
40
|
+
*/
|
|
29
41
|
|
|
30
|
-
if (data.options) {
|
|
31
|
-
const externalOptionsKeys = ['pragma', 'loosePragma', 'ignorePragma', 'scalars', 'strictNullability', 'regenerateCommand', 'readOnlyArray', 'splitTypes', 'generatedDirectory', 'exportAllObjectTypes', 'typeFileName'];
|
|
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
|
-
});
|
|
37
|
-
}
|
|
38
42
|
|
|
43
|
+
exports.loadConfigFile = loadConfigFile;
|
|
44
|
+
|
|
45
|
+
const loadSubConfigFile = configFile => {
|
|
46
|
+
var _data$options3, _data$excludes$map2, _data$excludes2, _data$options4, _data$extends;
|
|
47
|
+
|
|
48
|
+
const jsonData = _fs.default.readFileSync(configFile, 'utf8'); // eslint-disable-next-line flowtype-errors/uncovered
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
const data = JSON.parse(jsonData);
|
|
52
|
+
const toplevelKeys = ['excludes', 'options', 'extends'];
|
|
53
|
+
Object.keys(data).forEach(k => {
|
|
54
|
+
if (!toplevelKeys.includes(k)) {
|
|
55
|
+
throw new Error(`Invalid attribute in non-root config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(', ')}`);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
validateOptions(configFile, (_data$options3 = data.options) !== null && _data$options3 !== void 0 ? _data$options3 : {});
|
|
39
59
|
return {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
excludes: (_data$excludes$map2 = (_data$excludes2 = data.excludes) === null || _data$excludes2 === void 0 ? void 0 : _data$excludes2.map(string => new RegExp(string))) !== null && _data$excludes$map2 !== void 0 ? _data$excludes$map2 : [],
|
|
61
|
+
options: (_data$options4 = data.options) !== null && _data$options4 !== void 0 ? _data$options4 : {},
|
|
62
|
+
extends: (_data$extends = data.extends) !== null && _data$extends !== void 0 ? _data$extends : ''
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
exports.loadSubConfigFile = loadSubConfigFile;
|
|
67
|
+
|
|
68
|
+
const loadDirConfigFiles = (filesResponse, rootConfig) => {
|
|
69
|
+
const dirConfigMap = {}; // TODO: circular extends will cause infinite loop... consider instrumenting code to monitor for loops in the future?
|
|
70
|
+
|
|
71
|
+
const loadExtendedConfig = configPath => {
|
|
72
|
+
let dirConfig = loadSubConfigFile(configPath);
|
|
73
|
+
|
|
74
|
+
if (dirConfig.extends) {
|
|
75
|
+
const isRootConfig = dirConfig.extends === rootConfig.path;
|
|
76
|
+
const {
|
|
77
|
+
options,
|
|
78
|
+
excludes
|
|
79
|
+
} = isRootConfig ? rootConfig.config : addConfig(dirConfig.extends);
|
|
80
|
+
dirConfig = extendConfig({
|
|
81
|
+
options,
|
|
82
|
+
excludes
|
|
83
|
+
}, dirConfig);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return dirConfig;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const addConfig = configPath => {
|
|
90
|
+
const {
|
|
91
|
+
dir
|
|
92
|
+
} = _path.default.parse(configPath);
|
|
93
|
+
|
|
94
|
+
if (dirConfigMap[dir]) {
|
|
95
|
+
return dirConfigMap[dir];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
dirConfigMap[dir] = loadExtendedConfig(configPath);
|
|
99
|
+
return dirConfigMap[dir];
|
|
43
100
|
};
|
|
101
|
+
|
|
102
|
+
const extendConfig = (toExtend, current) => ({
|
|
103
|
+
// $FlowFixMe[exponential-spread]
|
|
104
|
+
options: { ...toExtend.options,
|
|
105
|
+
...current.options
|
|
106
|
+
},
|
|
107
|
+
excludes: Array.from(new Set([...toExtend.excludes, ...current.excludes]))
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
filesResponse.trim().split('\n').forEach(configPath => {
|
|
111
|
+
const {
|
|
112
|
+
dir
|
|
113
|
+
} = _path.default.parse(configPath);
|
|
114
|
+
|
|
115
|
+
if (dir && !dirConfigMap[dir]) {
|
|
116
|
+
dirConfigMap[dir] = loadExtendedConfig(configPath);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return dirConfigMap;
|
|
44
120
|
};
|
|
45
121
|
/**
|
|
46
122
|
* Loads a .json 'introspection query response', or a .graphql schema definition.
|
|
47
123
|
*/
|
|
48
124
|
|
|
49
125
|
|
|
50
|
-
exports.
|
|
126
|
+
exports.loadDirConfigFiles = loadDirConfigFiles;
|
|
51
127
|
|
|
52
128
|
const getSchemas = schemaFilePath => {
|
|
53
129
|
const raw = _fs.default.readFileSync(schemaFilePath, 'utf8');
|
|
@@ -70,4 +146,15 @@ const getSchemas = schemaFilePath => {
|
|
|
70
146
|
};
|
|
71
147
|
|
|
72
148
|
exports.getSchemas = getSchemas;
|
|
149
|
+
|
|
150
|
+
const validateOptions = (configFile, options) => {
|
|
151
|
+
if (options) {
|
|
152
|
+
const externalOptionsKeys = ['pragma', 'loosePragma', 'ignorePragma', 'scalars', 'strictNullability', 'regenerateCommand', 'readOnlyArray', 'splitTypes', 'generatedDirectory', 'exportAllObjectTypes', 'typeFileName', 'experimentalEnums'];
|
|
153
|
+
Object.keys(options).forEach(k => {
|
|
154
|
+
if (!externalOptionsKeys.includes(k)) {
|
|
155
|
+
throw new Error(`Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(', ')}`);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
};
|
|
73
160
|
//# sourceMappingURL=config.js.map
|
package/dist/cli/config.js.flow
CHANGED
|
@@ -18,6 +18,7 @@ import path from 'path';
|
|
|
18
18
|
export type CliConfig = {
|
|
19
19
|
excludes: Array<RegExp>,
|
|
20
20
|
schemaFilePath: string,
|
|
21
|
+
dumpOperations?: string,
|
|
21
22
|
options: ExternalOptions,
|
|
22
23
|
};
|
|
23
24
|
|
|
@@ -29,12 +30,18 @@ type JSONConfig = {
|
|
|
29
30
|
excludes?: Array<string>,
|
|
30
31
|
schemaFilePath: string,
|
|
31
32
|
options?: ExternalOptions,
|
|
33
|
+
dumpOperations?: string,
|
|
32
34
|
};
|
|
33
35
|
|
|
34
36
|
export const loadConfigFile = (configFile: string): CliConfig => {
|
|
35
37
|
// eslint-disable-next-line flowtype-errors/uncovered
|
|
36
38
|
const data: JSONConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
37
|
-
const toplevelKeys = [
|
|
39
|
+
const toplevelKeys = [
|
|
40
|
+
'excludes',
|
|
41
|
+
'schemaFilePath',
|
|
42
|
+
'options',
|
|
43
|
+
'dumpOperations',
|
|
44
|
+
];
|
|
38
45
|
Object.keys(data).forEach((k) => {
|
|
39
46
|
if (!toplevelKeys.includes(k)) {
|
|
40
47
|
throw new Error(
|
|
@@ -44,40 +51,104 @@ export const loadConfigFile = (configFile: string): CliConfig => {
|
|
|
44
51
|
);
|
|
45
52
|
}
|
|
46
53
|
});
|
|
47
|
-
|
|
48
|
-
const externalOptionsKeys = [
|
|
49
|
-
'pragma',
|
|
50
|
-
'loosePragma',
|
|
51
|
-
'ignorePragma',
|
|
52
|
-
'scalars',
|
|
53
|
-
'strictNullability',
|
|
54
|
-
'regenerateCommand',
|
|
55
|
-
'readOnlyArray',
|
|
56
|
-
'splitTypes',
|
|
57
|
-
'generatedDirectory',
|
|
58
|
-
'exportAllObjectTypes',
|
|
59
|
-
'typeFileName',
|
|
60
|
-
];
|
|
61
|
-
Object.keys(data.options).forEach((k) => {
|
|
62
|
-
if (!externalOptionsKeys.includes(k)) {
|
|
63
|
-
throw new Error(
|
|
64
|
-
`Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(
|
|
65
|
-
', ',
|
|
66
|
-
)}`,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
}
|
|
54
|
+
validateOptions(configFile, data.options ?? {});
|
|
71
55
|
return {
|
|
72
56
|
options: data.options ?? {},
|
|
73
57
|
excludes: data.excludes?.map((string) => new RegExp(string)) ?? [],
|
|
74
|
-
schemaFilePath: path.
|
|
75
|
-
|
|
76
|
-
data.schemaFilePath,
|
|
77
|
-
|
|
58
|
+
schemaFilePath: path.isAbsolute(data.schemaFilePath)
|
|
59
|
+
? data.schemaFilePath
|
|
60
|
+
: path.join(path.dirname(configFile), data.schemaFilePath),
|
|
61
|
+
dumpOperations: data.dumpOperations,
|
|
78
62
|
};
|
|
79
63
|
};
|
|
80
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Subdirectory config to extend or overwrite higher-level config.
|
|
67
|
+
* @param {string} extends - Path from root; optional field for a config file in a subdirectory. If left blank, config file will overwrite root for directory.
|
|
68
|
+
*/
|
|
69
|
+
type JSONSubConfig = {
|
|
70
|
+
excludes?: Array<string>,
|
|
71
|
+
options?: ExternalOptions,
|
|
72
|
+
extends?: string,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
type SubConfig = {
|
|
76
|
+
excludes: Array<RegExp>,
|
|
77
|
+
options: ExternalOptions,
|
|
78
|
+
extends?: string,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const loadSubConfigFile = (configFile: string): SubConfig => {
|
|
82
|
+
const jsonData = fs.readFileSync(configFile, 'utf8');
|
|
83
|
+
// eslint-disable-next-line flowtype-errors/uncovered
|
|
84
|
+
const data: JSONSubConfig = JSON.parse(jsonData);
|
|
85
|
+
const toplevelKeys = ['excludes', 'options', 'extends'];
|
|
86
|
+
Object.keys(data).forEach((k) => {
|
|
87
|
+
if (!toplevelKeys.includes(k)) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Invalid attribute in non-root config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(
|
|
90
|
+
', ',
|
|
91
|
+
)}`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
validateOptions(configFile, data.options ?? {});
|
|
96
|
+
return {
|
|
97
|
+
excludes: data.excludes?.map((string) => new RegExp(string)) ?? [],
|
|
98
|
+
options: data.options ?? {},
|
|
99
|
+
extends: data.extends ?? '',
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const loadDirConfigFiles = (
|
|
104
|
+
filesResponse: string,
|
|
105
|
+
rootConfig: {path: string, config: CliConfig},
|
|
106
|
+
): {[dir: string]: SubConfig} => {
|
|
107
|
+
const dirConfigMap: {[key: string]: SubConfig} = {};
|
|
108
|
+
|
|
109
|
+
// TODO: circular extends will cause infinite loop... consider instrumenting code to monitor for loops in the future?
|
|
110
|
+
const loadExtendedConfig = (configPath: string): SubConfig => {
|
|
111
|
+
let dirConfig = loadSubConfigFile(configPath);
|
|
112
|
+
if (dirConfig.extends) {
|
|
113
|
+
const isRootConfig = dirConfig.extends === rootConfig.path;
|
|
114
|
+
const {options, excludes} = isRootConfig
|
|
115
|
+
? rootConfig.config
|
|
116
|
+
: addConfig(dirConfig.extends);
|
|
117
|
+
dirConfig = extendConfig({options, excludes}, dirConfig);
|
|
118
|
+
}
|
|
119
|
+
return dirConfig;
|
|
120
|
+
};
|
|
121
|
+
const addConfig = (configPath) => {
|
|
122
|
+
const {dir} = path.parse(configPath);
|
|
123
|
+
if (dirConfigMap[dir]) {
|
|
124
|
+
return dirConfigMap[dir];
|
|
125
|
+
}
|
|
126
|
+
dirConfigMap[dir] = loadExtendedConfig(configPath);
|
|
127
|
+
return dirConfigMap[dir];
|
|
128
|
+
};
|
|
129
|
+
const extendConfig = (
|
|
130
|
+
toExtend: SubConfig,
|
|
131
|
+
current: SubConfig,
|
|
132
|
+
): SubConfig => ({
|
|
133
|
+
// $FlowFixMe[exponential-spread]
|
|
134
|
+
options: {...toExtend.options, ...current.options},
|
|
135
|
+
excludes: Array.from(
|
|
136
|
+
new Set([...toExtend.excludes, ...current.excludes]),
|
|
137
|
+
),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
filesResponse
|
|
141
|
+
.trim()
|
|
142
|
+
.split('\n')
|
|
143
|
+
.forEach((configPath) => {
|
|
144
|
+
const {dir} = path.parse(configPath);
|
|
145
|
+
if (dir && !dirConfigMap[dir]) {
|
|
146
|
+
dirConfigMap[dir] = loadExtendedConfig(configPath);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return dirConfigMap;
|
|
150
|
+
};
|
|
151
|
+
|
|
81
152
|
/**
|
|
82
153
|
* Loads a .json 'introspection query response', or a .graphql schema definition.
|
|
83
154
|
*/
|
|
@@ -103,3 +174,34 @@ export const getSchemas = (schemaFilePath: string): [GraphQLSchema, Schema] => {
|
|
|
103
174
|
return [schemaForValidation, schemaForTypeGeneration];
|
|
104
175
|
}
|
|
105
176
|
};
|
|
177
|
+
|
|
178
|
+
const validateOptions = (
|
|
179
|
+
configFile: string,
|
|
180
|
+
options: ExternalOptions,
|
|
181
|
+
): void => {
|
|
182
|
+
if (options) {
|
|
183
|
+
const externalOptionsKeys = [
|
|
184
|
+
'pragma',
|
|
185
|
+
'loosePragma',
|
|
186
|
+
'ignorePragma',
|
|
187
|
+
'scalars',
|
|
188
|
+
'strictNullability',
|
|
189
|
+
'regenerateCommand',
|
|
190
|
+
'readOnlyArray',
|
|
191
|
+
'splitTypes',
|
|
192
|
+
'generatedDirectory',
|
|
193
|
+
'exportAllObjectTypes',
|
|
194
|
+
'typeFileName',
|
|
195
|
+
'experimentalEnums',
|
|
196
|
+
];
|
|
197
|
+
Object.keys(options).forEach((k) => {
|
|
198
|
+
if (!externalOptionsKeys.includes(k)) {
|
|
199
|
+
throw new Error(
|
|
200
|
+
`Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(
|
|
201
|
+
', ',
|
|
202
|
+
)}`,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
};
|
package/dist/cli/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/config.js"],"names":["loadConfigFile","configFile","data","JSON","parse","fs","readFileSync","toplevelKeys","Object","keys","forEach","k","includes","Error","join","options","externalOptionsKeys","excludes","map","string","RegExp","schemaFilePath","path","dirname","getSchemas","raw","endsWith","schemaForValidation","queryResponse","descriptions","schemaForTypeGeneration","introspectionData"],"mappings":";;;;;;;AAKA;;AAEA;;AACA;;AAOA;;;;AAkBO,MAAMA,cAAc,GAAIC,UAAD,IAAmC;AAAA;;AAC7D;AACA,QAAMC,IAAgB,GAAGC,IAAI,CAACC,KAAL,CAAWC,YAAGC,YAAH,CAAgBL,UAAhB,EAA4B,MAA5B,CAAX,CAAzB;AACA,QAAMM,YAAY,GAAG,CAAC,UAAD,EAAa,gBAAb,EAA+B,SAA/B,CAArB;AACAC,EAAAA,MAAM,CAACC,IAAP,CAAYP,IAAZ,EAAkBQ,OAAlB,CAA2BC,CAAD,IAAO;AAC7B,QAAI,CAACJ,YAAY,CAACK,QAAb,CAAsBD,CAAtB,CAAL,EAA+B;AAC3B,YAAM,IAAIE,KAAJ,CACD,oCAAmCZ,UAAW,KAAIU,CAAE,yBAAwBJ,YAAY,CAACO,IAAb,CACzE,IADyE,CAE3E,EAHA,CAAN;AAKH;AACJ,GARD;;AASA,MAAIZ,IAAI,CAACa,OAAT,EAAkB;AACd,UAAMC,mBAAmB,GAAG,CACxB,QADwB,EAExB,aAFwB,EAGxB,cAHwB,EAIxB,SAJwB,EAKxB,mBALwB,EAMxB,mBANwB,EAOxB,eAPwB,EAQxB,YARwB,EASxB,oBATwB,EAUxB,sBAVwB,EAWxB,cAXwB,CAA5B;AAaAR,IAAAA,MAAM,CAACC,IAAP,CAAYP,IAAI,CAACa,OAAjB,EAA0BL,OAA1B,CAAmCC,CAAD,IAAO;AACrC,UAAI,CAACK,mBAAmB,CAACJ,QAApB,CAA6BD,CAA7B,CAAL,EAAsC;AAClC,cAAM,IAAIE,KAAJ,CACD,iCAAgCZ,UAAW,KAAIU,CAAE,sBAAqBK,mBAAmB,CAACF,IAApB,CACnE,IADmE,CAErE,EAHA,CAAN;AAKH;AACJ,KARD;AASH;;AACD,SAAO;AACHC,IAAAA,OAAO,mBAAEb,IAAI,CAACa,OAAP,yDAAkB,EADtB;AAEHE,IAAAA,QAAQ,0CAAEf,IAAI,CAACe,QAAP,mDAAE,eAAeC,GAAf,CAAoBC,MAAD,IAAY,IAAIC,MAAJ,CAAWD,MAAX,CAA/B,CAAF,mEAAwD,EAF7D;AAGHE,IAAAA,cAAc,EAAEC,cAAKR,IAAL,CACZQ,cAAKC,OAAL,CAAatB,UAAb,CADY,EAEZC,IAAI,CAACmB,cAFO;AAHb,GAAP;AAQH,CA7CM;AA+CP;AACA;AACA;;;;;AACO,MAAMG,UAAU,GAAIH,cAAD,IAAqD;AAC3E,QAAMI,GAAG,GAAGpB,YAAGC,YAAH,CAAgBe,cAAhB,EAAgC,MAAhC,CAAZ;;AACA,MAAIA,cAAc,CAACK,QAAf,CAAwB,UAAxB,CAAJ,EAAyC;AACrC,UAAMC,mBAAmB,GAAG,0BAAYF,GAAZ,CAA5B;AACA,UAAMG,aAAa,GAAG,0BAClBD,mBADkB,EAElB,oCAAsB;AAACE,MAAAA,YAAY,EAAE;AAAf,KAAtB,CAFkB,CAAtB;AAIA,UAAMC,uBAAuB,GAAG,+DAC5B;AACEF,IAAAA,aAAa,CAAC1B,IAFY,CAAhC;AAIA,WAAO,CAACyB,mBAAD,EAAsBG,uBAAtB,CAAP;AACH,GAXD,MAWO;AACH;AACA,UAAMC,iBAAqC,GAAG5B,IAAI,CAACC,KAAL,CAAWqB,GAAX,CAA9C;AACA,UAAME,mBAAmB,GAAG,gCAAkBI,iBAAlB,CAA5B;AACA,UAAMD,uBAAuB,GACzB,8DAA4BC,iBAA5B,CADJ;AAEA,WAAO,CAACJ,mBAAD,EAAsBG,uBAAtB,CAAP;AACH;AACJ,CArBM","sourcesContent":["// @flow\nimport type {ExternalOptions} from '../generateTypeFiles';\nimport type {Schema} from '../types';\nimport type {GraphQLSchema} from 'graphql/type/schema';\n\nimport {schemaFromIntrospectionData} from '../schemaFromIntrospectionData';\n\nimport fs from 'fs';\nimport {\n buildClientSchema,\n buildSchema,\n getIntrospectionQuery,\n graphqlSync,\n type IntrospectionQuery,\n} from 'graphql';\nimport path from 'path';\n\nexport type CliConfig = {\n excludes: Array<RegExp>,\n schemaFilePath: string,\n options: ExternalOptions,\n};\n\n/**\n * This is the json-compatible form of the config\n * object.\n */\ntype JSONConfig = {\n excludes?: Array<string>,\n schemaFilePath: string,\n options?: ExternalOptions,\n};\n\nexport const loadConfigFile = (configFile: string): CliConfig => {\n // eslint-disable-next-line flowtype-errors/uncovered\n const data: JSONConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));\n const toplevelKeys = ['excludes', 'schemaFilePath', 'options'];\n Object.keys(data).forEach((k) => {\n if (!toplevelKeys.includes(k)) {\n throw new Error(\n `Invalid attribute in config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(\n ', ',\n )}`,\n );\n }\n });\n if (data.options) {\n const externalOptionsKeys = [\n 'pragma',\n 'loosePragma',\n 'ignorePragma',\n 'scalars',\n 'strictNullability',\n 'regenerateCommand',\n 'readOnlyArray',\n 'splitTypes',\n 'generatedDirectory',\n 'exportAllObjectTypes',\n 'typeFileName',\n ];\n Object.keys(data.options).forEach((k) => {\n if (!externalOptionsKeys.includes(k)) {\n throw new Error(\n `Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(\n ', ',\n )}`,\n );\n }\n });\n }\n return {\n options: data.options ?? {},\n excludes: data.excludes?.map((string) => new RegExp(string)) ?? [],\n schemaFilePath: path.join(\n path.dirname(configFile),\n data.schemaFilePath,\n ),\n };\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"],"file":"config.js"}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/config.js"],"names":["loadConfigFile","configFile","data","JSON","parse","fs","readFileSync","toplevelKeys","Object","keys","forEach","k","includes","Error","join","validateOptions","options","excludes","map","string","RegExp","schemaFilePath","path","isAbsolute","dirname","dumpOperations","loadSubConfigFile","jsonData","extends","loadDirConfigFiles","filesResponse","rootConfig","dirConfigMap","loadExtendedConfig","configPath","dirConfig","isRootConfig","config","addConfig","extendConfig","dir","toExtend","current","Array","from","Set","trim","split","getSchemas","raw","endsWith","schemaForValidation","queryResponse","descriptions","schemaForTypeGeneration","introspectionData","externalOptionsKeys"],"mappings":";;;;;;;AAKA;;AAEA;;AACA;;AAOA;;;;AAoBO,MAAMA,cAAc,GAAIC,UAAD,IAAmC;AAAA;;AAC7D;AACA,QAAMC,IAAgB,GAAGC,IAAI,CAACC,KAAL,CAAWC,YAAGC,YAAH,CAAgBL,UAAhB,EAA4B,MAA5B,CAAX,CAAzB;AACA,QAAMM,YAAY,GAAG,CACjB,UADiB,EAEjB,gBAFiB,EAGjB,SAHiB,EAIjB,gBAJiB,CAArB;AAMAC,EAAAA,MAAM,CAACC,IAAP,CAAYP,IAAZ,EAAkBQ,OAAlB,CAA2BC,CAAD,IAAO;AAC7B,QAAI,CAACJ,YAAY,CAACK,QAAb,CAAsBD,CAAtB,CAAL,EAA+B;AAC3B,YAAM,IAAIE,KAAJ,CACD,oCAAmCZ,UAAW,KAAIU,CAAE,yBAAwBJ,YAAY,CAACO,IAAb,CACzE,IADyE,CAE3E,EAHA,CAAN;AAKH;AACJ,GARD;AASAC,EAAAA,eAAe,CAACd,UAAD,mBAAaC,IAAI,CAACc,OAAlB,yDAA6B,EAA7B,CAAf;AACA,SAAO;AACHA,IAAAA,OAAO,oBAAEd,IAAI,CAACc,OAAP,2DAAkB,EADtB;AAEHC,IAAAA,QAAQ,0CAAEf,IAAI,CAACe,QAAP,mDAAE,eAAeC,GAAf,CAAoBC,MAAD,IAAY,IAAIC,MAAJ,CAAWD,MAAX,CAA/B,CAAF,mEAAwD,EAF7D;AAGHE,IAAAA,cAAc,EAAEC,cAAKC,UAAL,CAAgBrB,IAAI,CAACmB,cAArB,IACVnB,IAAI,CAACmB,cADK,GAEVC,cAAKR,IAAL,CAAUQ,cAAKE,OAAL,CAAavB,UAAb,CAAV,EAAoCC,IAAI,CAACmB,cAAzC,CALH;AAMHI,IAAAA,cAAc,EAAEvB,IAAI,CAACuB;AANlB,GAAP;AAQH,CA3BM;AA6BP;AACA;AACA;AACA;;;;;AAaO,MAAMC,iBAAiB,GAAIzB,UAAD,IAAmC;AAAA;;AAChE,QAAM0B,QAAQ,GAAGtB,YAAGC,YAAH,CAAgBL,UAAhB,EAA4B,MAA5B,CAAjB,CADgE,CAEhE;;;AACA,QAAMC,IAAmB,GAAGC,IAAI,CAACC,KAAL,CAAWuB,QAAX,CAA5B;AACA,QAAMpB,YAAY,GAAG,CAAC,UAAD,EAAa,SAAb,EAAwB,SAAxB,CAArB;AACAC,EAAAA,MAAM,CAACC,IAAP,CAAYP,IAAZ,EAAkBQ,OAAlB,CAA2BC,CAAD,IAAO;AAC7B,QAAI,CAACJ,YAAY,CAACK,QAAb,CAAsBD,CAAtB,CAAL,EAA+B;AAC3B,YAAM,IAAIE,KAAJ,CACD,6CAA4CZ,UAAW,KAAIU,CAAE,yBAAwBJ,YAAY,CAACO,IAAb,CAClF,IADkF,CAEpF,EAHA,CAAN;AAKH;AACJ,GARD;AASAC,EAAAA,eAAe,CAACd,UAAD,oBAAaC,IAAI,CAACc,OAAlB,2DAA6B,EAA7B,CAAf;AACA,SAAO;AACHC,IAAAA,QAAQ,4CAAEf,IAAI,CAACe,QAAP,oDAAE,gBAAeC,GAAf,CAAoBC,MAAD,IAAY,IAAIC,MAAJ,CAAWD,MAAX,CAA/B,CAAF,qEAAwD,EAD7D;AAEHH,IAAAA,OAAO,oBAAEd,IAAI,CAACc,OAAP,2DAAkB,EAFtB;AAGHY,IAAAA,OAAO,mBAAE1B,IAAI,CAAC0B,OAAP,yDAAkB;AAHtB,GAAP;AAKH,CApBM;;;;AAsBA,MAAMC,kBAAkB,GAAG,CAC9BC,aAD8B,EAE9BC,UAF8B,KAGD;AAC7B,QAAMC,YAAwC,GAAG,EAAjD,CAD6B,CAG7B;;AACA,QAAMC,kBAAkB,GAAIC,UAAD,IAAmC;AAC1D,QAAIC,SAAS,GAAGT,iBAAiB,CAACQ,UAAD,CAAjC;;AACA,QAAIC,SAAS,CAACP,OAAd,EAAuB;AACnB,YAAMQ,YAAY,GAAGD,SAAS,CAACP,OAAV,KAAsBG,UAAU,CAACT,IAAtD;AACA,YAAM;AAACN,QAAAA,OAAD;AAAUC,QAAAA;AAAV,UAAsBmB,YAAY,GAClCL,UAAU,CAACM,MADuB,GAElCC,SAAS,CAACH,SAAS,CAACP,OAAX,CAFf;AAGAO,MAAAA,SAAS,GAAGI,YAAY,CAAC;AAACvB,QAAAA,OAAD;AAAUC,QAAAA;AAAV,OAAD,EAAsBkB,SAAtB,CAAxB;AACH;;AACD,WAAOA,SAAP;AACH,GAVD;;AAWA,QAAMG,SAAS,GAAIJ,UAAD,IAAgB;AAC9B,UAAM;AAACM,MAAAA;AAAD,QAAQlB,cAAKlB,KAAL,CAAW8B,UAAX,CAAd;;AACA,QAAIF,YAAY,CAACQ,GAAD,CAAhB,EAAuB;AACnB,aAAOR,YAAY,CAACQ,GAAD,CAAnB;AACH;;AACDR,IAAAA,YAAY,CAACQ,GAAD,CAAZ,GAAoBP,kBAAkB,CAACC,UAAD,CAAtC;AACA,WAAOF,YAAY,CAACQ,GAAD,CAAnB;AACH,GAPD;;AAQA,QAAMD,YAAY,GAAG,CACjBE,QADiB,EAEjBC,OAFiB,MAGJ;AACb;AACA1B,IAAAA,OAAO,EAAE,EAAC,GAAGyB,QAAQ,CAACzB,OAAb;AAAsB,SAAG0B,OAAO,CAAC1B;AAAjC,KAFI;AAGbC,IAAAA,QAAQ,EAAE0B,KAAK,CAACC,IAAN,CACN,IAAIC,GAAJ,CAAQ,CAAC,GAAGJ,QAAQ,CAACxB,QAAb,EAAuB,GAAGyB,OAAO,CAACzB,QAAlC,CAAR,CADM;AAHG,GAHI,CAArB;;AAWAa,EAAAA,aAAa,CACRgB,IADL,GAEKC,KAFL,CAEW,IAFX,EAGKrC,OAHL,CAGcwB,UAAD,IAAgB;AACrB,UAAM;AAACM,MAAAA;AAAD,QAAQlB,cAAKlB,KAAL,CAAW8B,UAAX,CAAd;;AACA,QAAIM,GAAG,IAAI,CAACR,YAAY,CAACQ,GAAD,CAAxB,EAA+B;AAC3BR,MAAAA,YAAY,CAACQ,GAAD,CAAZ,GAAoBP,kBAAkB,CAACC,UAAD,CAAtC;AACH;AACJ,GARL;AASA,SAAOF,YAAP;AACH,CA/CM;AAiDP;AACA;AACA;;;;;AACO,MAAMgB,UAAU,GAAI3B,cAAD,IAAqD;AAC3E,QAAM4B,GAAG,GAAG5C,YAAGC,YAAH,CAAgBe,cAAhB,EAAgC,MAAhC,CAAZ;;AACA,MAAIA,cAAc,CAAC6B,QAAf,CAAwB,UAAxB,CAAJ,EAAyC;AACrC,UAAMC,mBAAmB,GAAG,0BAAYF,GAAZ,CAA5B;AACA,UAAMG,aAAa,GAAG,0BAClBD,mBADkB,EAElB,oCAAsB;AAACE,MAAAA,YAAY,EAAE;AAAf,KAAtB,CAFkB,CAAtB;AAIA,UAAMC,uBAAuB,GAAG,+DAC5B;AACEF,IAAAA,aAAa,CAAClD,IAFY,CAAhC;AAIA,WAAO,CAACiD,mBAAD,EAAsBG,uBAAtB,CAAP;AACH,GAXD,MAWO;AACH;AACA,UAAMC,iBAAqC,GAAGpD,IAAI,CAACC,KAAL,CAAW6C,GAAX,CAA9C;AACA,UAAME,mBAAmB,GAAG,gCAAkBI,iBAAlB,CAA5B;AACA,UAAMD,uBAAuB,GACzB,8DAA4BC,iBAA5B,CADJ;AAEA,WAAO,CAACJ,mBAAD,EAAsBG,uBAAtB,CAAP;AACH;AACJ,CArBM;;;;AAuBP,MAAMvC,eAAe,GAAG,CACpBd,UADoB,EAEpBe,OAFoB,KAGb;AACP,MAAIA,OAAJ,EAAa;AACT,UAAMwC,mBAAmB,GAAG,CACxB,QADwB,EAExB,aAFwB,EAGxB,cAHwB,EAIxB,SAJwB,EAKxB,mBALwB,EAMxB,mBANwB,EAOxB,eAPwB,EAQxB,YARwB,EASxB,oBATwB,EAUxB,sBAVwB,EAWxB,cAXwB,EAYxB,mBAZwB,CAA5B;AAcAhD,IAAAA,MAAM,CAACC,IAAP,CAAYO,OAAZ,EAAqBN,OAArB,CAA8BC,CAAD,IAAO;AAChC,UAAI,CAAC6C,mBAAmB,CAAC5C,QAApB,CAA6BD,CAA7B,CAAL,EAAsC;AAClC,cAAM,IAAIE,KAAJ,CACD,iCAAgCZ,UAAW,KAAIU,CAAE,sBAAqB6C,mBAAmB,CAAC1C,IAApB,CACnE,IADmE,CAErE,EAHA,CAAN;AAKH;AACJ,KARD;AASH;AACJ,CA7BD","sourcesContent":["// @flow\nimport type {ExternalOptions} from '../generateTypeFiles';\nimport type {Schema} from '../types';\nimport type {GraphQLSchema} from 'graphql/type/schema';\n\nimport {schemaFromIntrospectionData} from '../schemaFromIntrospectionData';\n\nimport fs from 'fs';\nimport {\n buildClientSchema,\n buildSchema,\n getIntrospectionQuery,\n graphqlSync,\n type IntrospectionQuery,\n} from 'graphql';\nimport path from 'path';\n\nexport type CliConfig = {\n excludes: Array<RegExp>,\n schemaFilePath: string,\n dumpOperations?: string,\n options: ExternalOptions,\n};\n\n/**\n * This is the json-compatible form of the config\n * object.\n */\ntype JSONConfig = {\n excludes?: Array<string>,\n schemaFilePath: string,\n options?: ExternalOptions,\n dumpOperations?: string,\n};\n\nexport const loadConfigFile = (configFile: string): CliConfig => {\n // eslint-disable-next-line flowtype-errors/uncovered\n const data: JSONConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));\n const toplevelKeys = [\n 'excludes',\n 'schemaFilePath',\n 'options',\n 'dumpOperations',\n ];\n Object.keys(data).forEach((k) => {\n if (!toplevelKeys.includes(k)) {\n throw new Error(\n `Invalid attribute in config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(\n ', ',\n )}`,\n );\n }\n });\n validateOptions(configFile, data.options ?? {});\n return {\n options: data.options ?? {},\n excludes: data.excludes?.map((string) => new RegExp(string)) ?? [],\n schemaFilePath: path.isAbsolute(data.schemaFilePath)\n ? data.schemaFilePath\n : path.join(path.dirname(configFile), data.schemaFilePath),\n dumpOperations: data.dumpOperations,\n };\n};\n\n/**\n * Subdirectory config to extend or overwrite higher-level config.\n * @param {string} extends - Path from root; optional field for a config file in a subdirectory. If left blank, config file will overwrite root for directory.\n */\ntype JSONSubConfig = {\n excludes?: Array<string>,\n options?: ExternalOptions,\n extends?: string,\n};\n\ntype SubConfig = {\n excludes: Array<RegExp>,\n options: ExternalOptions,\n extends?: string,\n};\n\nexport const loadSubConfigFile = (configFile: string): SubConfig => {\n const jsonData = fs.readFileSync(configFile, 'utf8');\n // eslint-disable-next-line flowtype-errors/uncovered\n const data: JSONSubConfig = JSON.parse(jsonData);\n const toplevelKeys = ['excludes', 'options', 'extends'];\n Object.keys(data).forEach((k) => {\n if (!toplevelKeys.includes(k)) {\n throw new Error(\n `Invalid attribute in non-root config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(\n ', ',\n )}`,\n );\n }\n });\n validateOptions(configFile, data.options ?? {});\n return {\n excludes: data.excludes?.map((string) => new RegExp(string)) ?? [],\n options: data.options ?? {},\n extends: data.extends ?? '',\n };\n};\n\nexport const loadDirConfigFiles = (\n filesResponse: string,\n rootConfig: {path: string, config: CliConfig},\n): {[dir: string]: SubConfig} => {\n const dirConfigMap: {[key: string]: SubConfig} = {};\n\n // TODO: circular extends will cause infinite loop... consider instrumenting code to monitor for loops in the future?\n const loadExtendedConfig = (configPath: string): SubConfig => {\n let dirConfig = loadSubConfigFile(configPath);\n if (dirConfig.extends) {\n const isRootConfig = dirConfig.extends === rootConfig.path;\n const {options, excludes} = isRootConfig\n ? rootConfig.config\n : addConfig(dirConfig.extends);\n dirConfig = extendConfig({options, excludes}, dirConfig);\n }\n return dirConfig;\n };\n const addConfig = (configPath) => {\n const {dir} = path.parse(configPath);\n if (dirConfigMap[dir]) {\n return dirConfigMap[dir];\n }\n dirConfigMap[dir] = loadExtendedConfig(configPath);\n return dirConfigMap[dir];\n };\n const extendConfig = (\n toExtend: SubConfig,\n current: SubConfig,\n ): SubConfig => ({\n // $FlowFixMe[exponential-spread]\n options: {...toExtend.options, ...current.options},\n excludes: Array.from(\n new Set([...toExtend.excludes, ...current.excludes]),\n ),\n });\n\n filesResponse\n .trim()\n .split('\\n')\n .forEach((configPath) => {\n const {dir} = path.parse(configPath);\n if (dir && !dirConfigMap[dir]) {\n dirConfigMap[dir] = loadExtendedConfig(configPath);\n }\n });\n return dirConfigMap;\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\nconst validateOptions = (\n configFile: string,\n options: ExternalOptions,\n): void => {\n if (options) {\n const externalOptionsKeys = [\n 'pragma',\n 'loosePragma',\n 'ignorePragma',\n 'scalars',\n 'strictNullability',\n 'regenerateCommand',\n 'readOnlyArray',\n 'splitTypes',\n 'generatedDirectory',\n 'exportAllObjectTypes',\n 'typeFileName',\n 'experimentalEnums',\n ];\n Object.keys(options).forEach((k) => {\n if (!externalOptionsKeys.includes(k)) {\n throw new Error(\n `Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(\n ', ',\n )}`,\n );\n }\n });\n }\n};\n"],"file":"config.js"}
|