@khanacademy/graphql-flow 3.0.0 → 3.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/.eslintrc.js +15 -4
- package/.github/workflows/changeset-release.yml +3 -5
- package/.github/workflows/pr-checks.yml +17 -17
- package/.prettierrc +2 -2
- package/.vscode/settings.json +6 -0
- package/CHANGELOG.md +12 -0
- package/dist/cli/config.js +6 -15
- package/dist/cli/run.js +31 -37
- package/dist/enums.js +9 -9
- package/dist/generateResponseType.js +36 -40
- package/dist/generateTypeFiles.js +10 -10
- package/dist/generateVariablesType.js +12 -13
- package/dist/index.js +4 -6
- package/dist/parser/parse.js +47 -53
- package/dist/parser/resolve.js +16 -16
- package/dist/parser/utils.js +25 -11
- package/dist/schemaFromIntrospectionData.js +5 -5
- package/dist/utils.js +8 -8
- package/package.json +12 -13
- package/src/__test__/generateTypeFileContents.test.ts +26 -25
- package/src/__test__/graphql-flow.test.ts +32 -33
- package/src/__test__/processPragmas.test.ts +14 -13
- package/src/cli/__test__/config.test.ts +51 -56
- package/src/cli/config.ts +23 -20
- package/src/cli/run.ts +45 -46
- package/src/enums.ts +17 -17
- package/src/generateResponseType.ts +120 -91
- package/src/generateTypeFiles.ts +24 -22
- package/src/generateVariablesType.ts +20 -20
- package/src/index.ts +28 -29
- package/src/parser/__test__/parse.test.ts +114 -23
- package/src/parser/__test__/utils.test.ts +80 -0
- package/src/parser/parse.ts +122 -106
- package/src/parser/resolve.ts +61 -34
- package/src/parser/utils.ts +28 -11
- package/src/schemaFromIntrospectionData.ts +10 -8
- package/src/types.ts +57 -53
- package/src/utils.ts +30 -16
- package/tools/find-files-with-gql.ts +7 -11
package/.eslintrc.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
extends: ['@khanacademy'],
|
|
3
2
|
root: true,
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
plugins: ["prettier", "jest"],
|
|
4
|
+
extends: ["eslint:recommended", "prettier"],
|
|
5
|
+
parser: "@typescript-eslint/parser",
|
|
6
|
+
parserOptions: {
|
|
7
|
+
sourceType: "module",
|
|
8
|
+
ecmaVersion: 2020,
|
|
9
|
+
},
|
|
6
10
|
rules: {
|
|
7
|
-
|
|
11
|
+
"prettier/prettier": "error",
|
|
12
|
+
"no-unused-vars": "off",
|
|
13
|
+
"no-case-declarations": "off",
|
|
14
|
+
},
|
|
15
|
+
env: {
|
|
16
|
+
es6: true,
|
|
17
|
+
node: true,
|
|
18
|
+
jest: true,
|
|
8
19
|
},
|
|
9
20
|
};
|
|
@@ -31,12 +31,10 @@ jobs:
|
|
|
31
31
|
name: Release
|
|
32
32
|
runs-on: ubuntu-latest
|
|
33
33
|
steps:
|
|
34
|
-
- uses: actions/checkout@
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: Khan/actions@shared-node-cache-v2
|
|
35
36
|
with:
|
|
36
|
-
|
|
37
|
-
- uses: Khan/actions@shared-node-cache-v0.0.2
|
|
38
|
-
with:
|
|
39
|
-
node-version: 16.x
|
|
37
|
+
node-version: 20.x
|
|
40
38
|
|
|
41
39
|
- name: Create Release Pull Request or Publish to npm
|
|
42
40
|
id: changesets
|
|
@@ -14,45 +14,45 @@ jobs:
|
|
|
14
14
|
strategy:
|
|
15
15
|
matrix:
|
|
16
16
|
os: [ubuntu-latest]
|
|
17
|
-
node-version: [
|
|
17
|
+
node-version: [20.x]
|
|
18
18
|
steps:
|
|
19
|
-
- uses: actions/checkout@
|
|
20
|
-
- uses: Khan/actions@shared-node-cache-
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: Khan/actions@shared-node-cache-v2
|
|
21
21
|
with:
|
|
22
22
|
node-version: ${{ matrix.node-version }}
|
|
23
23
|
|
|
24
24
|
- name: Get All Changed Files
|
|
25
|
-
uses: Khan/actions@get-changed-files-
|
|
25
|
+
uses: Khan/actions@get-changed-files-v2
|
|
26
26
|
id: changed
|
|
27
27
|
|
|
28
|
-
- id:
|
|
29
|
-
name: Find .
|
|
30
|
-
uses: Khan/actions@filter-files-
|
|
28
|
+
- id: ts-files
|
|
29
|
+
name: Find .ts changed files
|
|
30
|
+
uses: Khan/actions@filter-files-v1
|
|
31
31
|
with:
|
|
32
32
|
changed-files: ${{ steps.changed.outputs.files }}
|
|
33
|
-
extensions: '.
|
|
33
|
+
extensions: '.ts'
|
|
34
34
|
|
|
35
|
-
- name: Run
|
|
36
|
-
if: steps.
|
|
37
|
-
run: yarn
|
|
35
|
+
- name: Run TypeScript
|
|
36
|
+
if: steps.ts-files.outputs.filtered != '[]'
|
|
37
|
+
run: yarn tsc
|
|
38
38
|
|
|
39
39
|
- id: eslint-reset
|
|
40
|
-
uses: Khan/actions@filter-files-
|
|
40
|
+
uses: Khan/actions@filter-files-v1
|
|
41
41
|
name: Files that would trigger a full eslint run
|
|
42
42
|
with:
|
|
43
43
|
changed-files: ${{ steps.changed.outputs.files }}
|
|
44
44
|
files: '.eslintrc.js,package.json,.eslintignore'
|
|
45
45
|
|
|
46
|
-
- name:
|
|
46
|
+
- name: ESlint
|
|
47
47
|
uses: Khan/actions@full-or-limited-v0
|
|
48
48
|
with:
|
|
49
49
|
full-trigger: ${{ steps.eslint-reset.outputs.filtered }}
|
|
50
|
-
full: yarn eslint
|
|
51
|
-
limited-trigger: ${{ steps.
|
|
50
|
+
full: yarn eslint src/**/*.ts
|
|
51
|
+
limited-trigger: ${{ steps.ts-files.outputs.filtered }}
|
|
52
52
|
limited: yarn eslint {}
|
|
53
53
|
|
|
54
54
|
- id: jest-reset
|
|
55
|
-
uses: Khan/actions@filter-files-
|
|
55
|
+
uses: Khan/actions@filter-files-v1
|
|
56
56
|
name: Files that would trigger a full jest run
|
|
57
57
|
with:
|
|
58
58
|
changed-files: ${{ steps.changed.outputs.files }}
|
|
@@ -63,5 +63,5 @@ jobs:
|
|
|
63
63
|
with:
|
|
64
64
|
full-trigger: ${{ steps.jest-reset.outputs.filtered }}
|
|
65
65
|
full: yarn jest
|
|
66
|
-
limited-trigger: ${{ steps.
|
|
66
|
+
limited-trigger: ${{ steps.ts-files.outputs.filtered }}
|
|
67
67
|
limited: yarn jest --findRelatedTests {}
|
package/.prettierrc
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @khanacademy/graphql-flow
|
|
2
2
|
|
|
3
|
+
## 3.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d872096: Add alias resolution.
|
|
8
|
+
|
|
9
|
+
## 3.0.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- c6be76f: Search through untracked files for graphql-tag. Don't error out on files that can't be found.
|
|
14
|
+
|
|
3
15
|
## 3.0.0
|
|
4
16
|
|
|
5
17
|
### Major Changes
|
package/dist/cli/config.js
CHANGED
|
@@ -17,27 +17,20 @@ var _jsonschema = require("jsonschema");
|
|
|
17
17
|
|
|
18
18
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
19
|
|
|
20
|
-
// eslint-disable-line flowtype-errors/uncovered
|
|
21
|
-
// eslint-disable-line flowtype-errors/uncovered
|
|
22
20
|
const validateOrThrow = (value, jsonSchema) => {
|
|
23
|
-
/* eslint-disable flowtype-errors/uncovered */
|
|
24
21
|
const result = (0, _jsonschema.validate)(value, jsonSchema);
|
|
25
22
|
|
|
26
23
|
if (!result.valid) {
|
|
27
|
-
throw new Error(result.errors.map(error => error.toString()).join(
|
|
24
|
+
throw new Error(result.errors.map(error => error.toString()).join("\n"));
|
|
28
25
|
}
|
|
29
|
-
/* eslint-enable flowtype-errors/uncovered */
|
|
30
|
-
|
|
31
26
|
};
|
|
32
27
|
|
|
33
28
|
exports.validateOrThrow = validateOrThrow;
|
|
34
29
|
|
|
35
30
|
const loadConfigFile = configFile => {
|
|
36
|
-
const data = require(configFile);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
validateOrThrow(data, _schema.default); // eslint-disable-line flowtype-errors/uncovered
|
|
31
|
+
const data = require(configFile);
|
|
40
32
|
|
|
33
|
+
validateOrThrow(data, _schema.default);
|
|
41
34
|
return data;
|
|
42
35
|
};
|
|
43
36
|
/**
|
|
@@ -48,9 +41,9 @@ const loadConfigFile = configFile => {
|
|
|
48
41
|
exports.loadConfigFile = loadConfigFile;
|
|
49
42
|
|
|
50
43
|
const getSchemas = schemaFilePath => {
|
|
51
|
-
const raw = _fs.default.readFileSync(schemaFilePath,
|
|
44
|
+
const raw = _fs.default.readFileSync(schemaFilePath, "utf8");
|
|
52
45
|
|
|
53
|
-
if (schemaFilePath.endsWith(
|
|
46
|
+
if (schemaFilePath.endsWith(".graphql")) {
|
|
54
47
|
const schemaForValidation = (0, _graphql.buildSchema)(raw);
|
|
55
48
|
const queryResponse = (0, _graphql.graphqlSync)({
|
|
56
49
|
schema: schemaForValidation,
|
|
@@ -58,11 +51,9 @@ const getSchemas = schemaFilePath => {
|
|
|
58
51
|
descriptions: true
|
|
59
52
|
})
|
|
60
53
|
});
|
|
61
|
-
const schemaForTypeGeneration = (0, _schemaFromIntrospectionData.schemaFromIntrospectionData)(
|
|
62
|
-
queryResponse.data);
|
|
54
|
+
const schemaForTypeGeneration = (0, _schemaFromIntrospectionData.schemaFromIntrospectionData)(queryResponse.data);
|
|
63
55
|
return [schemaForValidation, schemaForTypeGeneration];
|
|
64
56
|
} else {
|
|
65
|
-
// eslint-disable-next-line flowtype-errors/uncovered
|
|
66
57
|
const introspectionData = JSON.parse(raw);
|
|
67
58
|
const schemaForValidation = (0, _graphql.buildClientSchema)(introspectionData);
|
|
68
59
|
const schemaForTypeGeneration = (0, _schemaFromIntrospectionData.schemaFromIntrospectionData)(introspectionData);
|
package/dist/cli/run.js
CHANGED
|
@@ -27,8 +27,6 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
|
|
|
27
27
|
|
|
28
28
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
29
29
|
|
|
30
|
-
// eslint-disable-line flowtype-errors/uncovered
|
|
31
|
-
|
|
32
30
|
/**
|
|
33
31
|
* This CLI tool executes the following steps:
|
|
34
32
|
* 1) parse & validate config file
|
|
@@ -42,20 +40,23 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
42
40
|
|
|
43
41
|
/** Step (1) */
|
|
44
42
|
const findGraphqlTagReferences = root => {
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
// NOTE(john): We want to include untracked files here so that we can
|
|
44
|
+
// generate types for them. This is useful for when we have a new file
|
|
45
|
+
// that we want to generate types for, but we haven't committed it yet.
|
|
46
|
+
const response = (0, _child_process.execSync)("git grep -I --word-regexp --name-only --fixed-strings --untracked 'graphql-tag' -- '*.js' '*.jsx' '*.ts' '*.tsx'", {
|
|
47
|
+
encoding: "utf8",
|
|
47
48
|
cwd: root
|
|
48
49
|
});
|
|
49
|
-
return response.trim().split(
|
|
50
|
+
return response.trim().split("\n").map(relative => _path.default.join(root, relative));
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
const [_, __, configFilePath, ...cliFiles] = process.argv;
|
|
53
54
|
|
|
54
|
-
if (configFilePath ===
|
|
55
|
+
if (configFilePath === "-h" || configFilePath === "--help" || configFilePath === "help" || !configFilePath) {
|
|
55
56
|
console.log(`graphql-flow
|
|
56
57
|
|
|
57
58
|
Usage: graphql-flow [configFile.json] [filesToCrawl...]`);
|
|
58
|
-
process.exit(1);
|
|
59
|
+
process.exit(1);
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
const makeAbsPath = (maybeRelativePath, basePath) => {
|
|
@@ -67,29 +68,29 @@ const config = (0, _config.loadConfigFile)(absConfigPath);
|
|
|
67
68
|
const inputFiles = cliFiles.length ? cliFiles : findGraphqlTagReferences(makeAbsPath(config.crawl.root, _path.default.dirname(absConfigPath)));
|
|
68
69
|
/** Step (2) */
|
|
69
70
|
|
|
70
|
-
const files = (0, _parse.processFiles)(inputFiles, f => {
|
|
71
|
+
const files = (0, _parse.processFiles)(inputFiles, config, f => {
|
|
71
72
|
if ((0, _fs.existsSync)(f)) {
|
|
72
|
-
return (0, _fs.readFileSync)(f,
|
|
73
|
+
return (0, _fs.readFileSync)(f, "utf8");
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
if ((0, _fs.existsSync)(f +
|
|
76
|
+
if ((0, _fs.existsSync)(f + ".js")) {
|
|
76
77
|
return {
|
|
77
|
-
text: (0, _fs.readFileSync)(f +
|
|
78
|
-
resolvedPath: f +
|
|
78
|
+
text: (0, _fs.readFileSync)(f + ".js", "utf8"),
|
|
79
|
+
resolvedPath: f + ".js"
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
if ((0, _fs.existsSync)(f +
|
|
83
|
+
if ((0, _fs.existsSync)(f + ".ts")) {
|
|
83
84
|
return {
|
|
84
|
-
text: (0, _fs.readFileSync)(f +
|
|
85
|
-
resolvedPath: f +
|
|
85
|
+
text: (0, _fs.readFileSync)(f + ".ts", "utf8"),
|
|
86
|
+
resolvedPath: f + ".ts"
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
if ((0, _fs.existsSync)(f +
|
|
90
|
+
if ((0, _fs.existsSync)(f + ".tsx")) {
|
|
90
91
|
return {
|
|
91
|
-
text: (0, _fs.readFileSync)(f +
|
|
92
|
-
resolvedPath: f +
|
|
92
|
+
text: (0, _fs.readFileSync)(f + ".tsx", "utf8"),
|
|
93
|
+
resolvedPath: f + ".tsx"
|
|
93
94
|
};
|
|
94
95
|
}
|
|
95
96
|
|
|
@@ -109,8 +110,8 @@ Object.keys(files).forEach(key => {
|
|
|
109
110
|
});
|
|
110
111
|
|
|
111
112
|
if (filesHadErrors) {
|
|
112
|
-
console.error(
|
|
113
|
-
process.exit(1);
|
|
113
|
+
console.error("Aborting");
|
|
114
|
+
process.exit(1);
|
|
114
115
|
}
|
|
115
116
|
/** Step (3) */
|
|
116
117
|
|
|
@@ -118,17 +119,17 @@ if (filesHadErrors) {
|
|
|
118
119
|
const {
|
|
119
120
|
resolved,
|
|
120
121
|
errors
|
|
121
|
-
} = (0, _resolve.resolveDocuments)(files);
|
|
122
|
+
} = (0, _resolve.resolveDocuments)(files, config);
|
|
122
123
|
|
|
123
124
|
if (errors.length) {
|
|
124
125
|
errors.forEach(error => {
|
|
125
126
|
console.error(`Resolution error ${error.message} in ${error.loc.path}`);
|
|
126
127
|
});
|
|
127
|
-
console.error(
|
|
128
|
-
process.exit(1);
|
|
128
|
+
console.error("Aborting");
|
|
129
|
+
process.exit(1);
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
console.log(Object.keys(resolved).length,
|
|
132
|
+
console.log(Object.keys(resolved).length, "resolved queries");
|
|
132
133
|
/** Step (4) */
|
|
133
134
|
|
|
134
135
|
const schemaCache = {};
|
|
@@ -150,15 +151,14 @@ Object.keys(resolved).forEach(filePathAndLine => {
|
|
|
150
151
|
} = resolved[filePathAndLine];
|
|
151
152
|
const hasNonFragments = document.definitions.some(({
|
|
152
153
|
kind
|
|
153
|
-
}) => kind !==
|
|
154
|
+
}) => kind !== "FragmentDefinition");
|
|
154
155
|
const rawSource = raw.literals[0];
|
|
155
156
|
const generateConfig = (0, _config.findApplicableConfig)( // strip off the trailing line number, e.g. `:23`
|
|
156
|
-
filePathAndLine.split(
|
|
157
|
+
filePathAndLine.split(":")[0], config.generate);
|
|
157
158
|
|
|
158
159
|
if (!generateConfig) {
|
|
159
160
|
return; // no generate config matches, bail
|
|
160
|
-
}
|
|
161
|
-
|
|
161
|
+
}
|
|
162
162
|
|
|
163
163
|
const withTypeNames = (0, _apolloUtilities.addTypenameToDocument)(document);
|
|
164
164
|
const printed = (0, _printer.print)(withTypeNames);
|
|
@@ -180,9 +180,7 @@ Object.keys(resolved).forEach(filePathAndLine => {
|
|
|
180
180
|
const [schemaForValidation, schemaForTypeGeneration] = getCachedSchemas(generateConfig.schemaFilePath);
|
|
181
181
|
|
|
182
182
|
if (hasNonFragments) {
|
|
183
|
-
/* eslint-disable flowtype-errors/uncovered */
|
|
184
183
|
const errors = (0, _validation.validate)(schemaForValidation, withTypeNames);
|
|
185
|
-
/* eslint-disable flowtype-errors/uncovered */
|
|
186
184
|
|
|
187
185
|
if (errors.length) {
|
|
188
186
|
errors.forEach(error => {
|
|
@@ -192,24 +190,20 @@ Object.keys(resolved).forEach(filePathAndLine => {
|
|
|
192
190
|
validationFailures++;
|
|
193
191
|
});
|
|
194
192
|
}
|
|
195
|
-
/* eslint-enable flowtype-errors/uncovered */
|
|
196
|
-
|
|
197
193
|
}
|
|
198
194
|
|
|
199
195
|
try {
|
|
200
|
-
(0, _generateTypeFiles.generateTypeFiles)(raw.loc.path, schemaForTypeGeneration, withTypeNames, generateConfig);
|
|
196
|
+
(0, _generateTypeFiles.generateTypeFiles)(raw.loc.path, schemaForTypeGeneration, withTypeNames, generateConfig);
|
|
201
197
|
} catch (err) {
|
|
202
198
|
console.error(`Error while generating operation from ${raw.loc.path}`);
|
|
203
|
-
console.error(printed);
|
|
204
|
-
|
|
199
|
+
console.error(printed);
|
|
205
200
|
console.error(err);
|
|
206
201
|
validationFailures++;
|
|
207
202
|
}
|
|
208
203
|
});
|
|
209
204
|
|
|
210
205
|
if (validationFailures) {
|
|
211
|
-
console.error(`Encountered ${validationFailures} validation failures while printing types.`);
|
|
212
|
-
|
|
206
|
+
console.error(`Encountered ${validationFailures} validation failures while printing types.`);
|
|
213
207
|
process.exit(1);
|
|
214
208
|
}
|
|
215
209
|
|
package/dist/enums.js
CHANGED
|
@@ -31,10 +31,10 @@ exports.experimentalEnumTypeToFlow = experimentalEnumTypeToFlow;
|
|
|
31
31
|
|
|
32
32
|
const enumTypeToFlow = (ctx, name) => {
|
|
33
33
|
const enumConfig = ctx.schema.enumsByName[name];
|
|
34
|
-
let combinedDescription = enumConfig.enumValues.map(n => `- ${n.name}` + (n.description ?
|
|
34
|
+
let combinedDescription = enumConfig.enumValues.map(n => `- ${n.name}` + (n.description ? "\n\n " + n.description.replace(/\n/g, "\n ") : "")).join("\n");
|
|
35
35
|
|
|
36
36
|
if (enumConfig.description) {
|
|
37
|
-
combinedDescription = enumConfig.description +
|
|
37
|
+
combinedDescription = enumConfig.description + "\n\n" + combinedDescription;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
return ctx.experimentalEnumsMap ? experimentalEnumTypeToFlow(ctx, enumConfig, combinedDescription) : (0, _utils.maybeAddDescriptionComment)(combinedDescription, babelTypes.tsUnionType(enumConfig.enumValues.map(n => babelTypes.tsLiteralType(babelTypes.stringLiteral(n.name)))));
|
|
@@ -42,13 +42,13 @@ const enumTypeToFlow = (ctx, name) => {
|
|
|
42
42
|
|
|
43
43
|
exports.enumTypeToFlow = enumTypeToFlow;
|
|
44
44
|
const builtinScalars = {
|
|
45
|
-
Boolean:
|
|
46
|
-
String:
|
|
47
|
-
DateTime:
|
|
48
|
-
Date:
|
|
49
|
-
ID:
|
|
50
|
-
Int:
|
|
51
|
-
Float:
|
|
45
|
+
Boolean: "boolean",
|
|
46
|
+
String: "string",
|
|
47
|
+
DateTime: "string",
|
|
48
|
+
Date: "string",
|
|
49
|
+
ID: "string",
|
|
50
|
+
Int: "number",
|
|
51
|
+
Float: "number"
|
|
52
52
|
};
|
|
53
53
|
exports.builtinScalars = builtinScalars;
|
|
54
54
|
|
|
@@ -20,10 +20,8 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
20
20
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
21
|
|
|
22
22
|
/* eslint-disable no-console */
|
|
23
|
-
// eslint-disable-line flowtype-errors/uncovered
|
|
24
23
|
const generateResponseType = (schema, query, ctx) => {
|
|
25
|
-
const ast = querySelectionToObjectType(ctx, query.selectionSet.selections, query.operation ===
|
|
26
|
-
|
|
24
|
+
const ast = querySelectionToObjectType(ctx, query.selectionSet.selections, query.operation === "mutation" ? schema.typesByName.Mutation : schema.typesByName.Query, query.operation === "mutation" ? "mutation" : "query");
|
|
27
25
|
return (0, _generator.default)(ast).code;
|
|
28
26
|
};
|
|
29
27
|
|
|
@@ -31,15 +29,15 @@ exports.generateResponseType = generateResponseType;
|
|
|
31
29
|
|
|
32
30
|
const sortedObjectTypeAnnotation = (ctx, properties) => {
|
|
33
31
|
const obj = (0, _utils.objectTypeFromProperties)(properties.sort((a, b) => {
|
|
34
|
-
if (a.type ===
|
|
35
|
-
const aName = a.key.type ===
|
|
36
|
-
const bName = b.key.type ===
|
|
32
|
+
if (a.type === "TSPropertySignature" && b.type === "TSPropertySignature") {
|
|
33
|
+
const aName = a.key.type === "Identifier" ? a.key.name : "";
|
|
34
|
+
const bName = b.key.type === "Identifier" ? b.key.name : "";
|
|
37
35
|
return aName < bName ? -1 : 1;
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
return 0;
|
|
41
39
|
}));
|
|
42
|
-
const name = ctx.path.join(
|
|
40
|
+
const name = ctx.path.join("_");
|
|
43
41
|
const isTopLevelType = ctx.path.length <= 1;
|
|
44
42
|
|
|
45
43
|
if (ctx.allObjectTypes != null && !isTopLevelType) {
|
|
@@ -62,8 +60,7 @@ const generateFragmentType = (schema, fragment, ctx) => {
|
|
|
62
60
|
ast = unionOrInterfaceToFlow(ctx, ctx.schema.unionsByName[onType], fragment.selectionSet.selections);
|
|
63
61
|
} else {
|
|
64
62
|
throw new Error(`Unknown ${onType}`);
|
|
65
|
-
}
|
|
66
|
-
|
|
63
|
+
}
|
|
67
64
|
|
|
68
65
|
return (0, _generator.default)(ast).code;
|
|
69
66
|
};
|
|
@@ -71,54 +68,54 @@ const generateFragmentType = (schema, fragment, ctx) => {
|
|
|
71
68
|
exports.generateFragmentType = generateFragmentType;
|
|
72
69
|
|
|
73
70
|
const _typeToFlow = (ctx, type, selection) => {
|
|
74
|
-
if (type.kind ===
|
|
71
|
+
if (type.kind === "SCALAR") {
|
|
75
72
|
return (0, _enums.scalarTypeToFlow)(ctx, type.name);
|
|
76
73
|
}
|
|
77
74
|
|
|
78
|
-
if (type.kind ===
|
|
79
|
-
return babelTypes.tsTypeReference(ctx.readOnlyArray ? babelTypes.identifier(
|
|
75
|
+
if (type.kind === "LIST") {
|
|
76
|
+
return babelTypes.tsTypeReference(ctx.readOnlyArray ? babelTypes.identifier("ReadonlyArray") : babelTypes.identifier("Array"), babelTypes.tsTypeParameterInstantiation([typeToFlow(ctx, type.ofType, selection)]));
|
|
80
77
|
}
|
|
81
78
|
|
|
82
|
-
if (type.kind ===
|
|
79
|
+
if (type.kind === "UNION") {
|
|
83
80
|
const union = ctx.schema.unionsByName[type.name];
|
|
84
81
|
|
|
85
82
|
if (!selection.selectionSet) {
|
|
86
|
-
console.log(
|
|
83
|
+
console.log("no selection set", selection);
|
|
87
84
|
return babelTypes.tsAnyKeyword();
|
|
88
85
|
}
|
|
89
86
|
|
|
90
87
|
return unionOrInterfaceToFlow(ctx, union, selection.selectionSet.selections);
|
|
91
88
|
}
|
|
92
89
|
|
|
93
|
-
if (type.kind ===
|
|
90
|
+
if (type.kind === "INTERFACE") {
|
|
94
91
|
if (!selection.selectionSet) {
|
|
95
|
-
console.log(
|
|
92
|
+
console.log("no selection set", selection);
|
|
96
93
|
return babelTypes.tsAnyKeyword();
|
|
97
94
|
}
|
|
98
95
|
|
|
99
96
|
return unionOrInterfaceToFlow(ctx, ctx.schema.interfacesByName[type.name], selection.selectionSet.selections);
|
|
100
97
|
}
|
|
101
98
|
|
|
102
|
-
if (type.kind ===
|
|
99
|
+
if (type.kind === "ENUM") {
|
|
103
100
|
return (0, _enums.enumTypeToFlow)(ctx, type.name);
|
|
104
101
|
}
|
|
105
102
|
|
|
106
|
-
if (type.kind !==
|
|
107
|
-
console.log(
|
|
103
|
+
if (type.kind !== "OBJECT") {
|
|
104
|
+
console.log("not object", type);
|
|
108
105
|
return babelTypes.tsAnyKeyword();
|
|
109
106
|
}
|
|
110
107
|
|
|
111
108
|
const tname = type.name;
|
|
112
109
|
|
|
113
110
|
if (!ctx.schema.typesByName[tname]) {
|
|
114
|
-
console.log(
|
|
111
|
+
console.log("unknown referenced type", tname);
|
|
115
112
|
return babelTypes.tsAnyKeyword();
|
|
116
113
|
}
|
|
117
114
|
|
|
118
115
|
const childType = ctx.schema.typesByName[tname];
|
|
119
116
|
|
|
120
117
|
if (!selection.selectionSet) {
|
|
121
|
-
console.log(
|
|
118
|
+
console.log("no selection set", selection);
|
|
122
119
|
return babelTypes.tsAnyKeyword();
|
|
123
120
|
}
|
|
124
121
|
|
|
@@ -127,7 +124,7 @@ const _typeToFlow = (ctx, type, selection) => {
|
|
|
127
124
|
|
|
128
125
|
const typeToFlow = (ctx, type, selection) => {
|
|
129
126
|
// throw new Error('npoe');
|
|
130
|
-
if (type.kind ===
|
|
127
|
+
if (type.kind === "NON_NULL") {
|
|
131
128
|
return _typeToFlow(ctx, type.ofType, selection);
|
|
132
129
|
} // If we don'babelTypes care about strict nullability checking, then pretend everything is non-null
|
|
133
130
|
|
|
@@ -150,10 +147,10 @@ const ensureOnlyOneTypenameProperty = properties => {
|
|
|
150
147
|
// The apollo-utilities "addTypeName" utility will add it
|
|
151
148
|
// even if it's already specified :( so we have to filter out
|
|
152
149
|
// the extra one here.
|
|
153
|
-
if (type.type ===
|
|
150
|
+
if (type.type === "TSPropertySignature" && type.key.type === "Identifier" && type.key.name === "__typename") {
|
|
154
151
|
var _type$typeAnnotation;
|
|
155
152
|
|
|
156
|
-
const name = ((_type$typeAnnotation = type.typeAnnotation) === null || _type$typeAnnotation === void 0 ? void 0 : _type$typeAnnotation.typeAnnotation.type) ===
|
|
153
|
+
const name = ((_type$typeAnnotation = type.typeAnnotation) === null || _type$typeAnnotation === void 0 ? void 0 : _type$typeAnnotation.typeAnnotation.type) === "TSLiteralType" && type.typeAnnotation.typeAnnotation.literal.type === "StringLiteral" ? type.typeAnnotation.typeAnnotation.literal.value : "INVALID";
|
|
157
154
|
|
|
158
155
|
if (seenTypeName) {
|
|
159
156
|
if (name !== seenTypeName) {
|
|
@@ -177,7 +174,7 @@ const querySelectionToObjectType = (ctx, selections, type, typeName) => {
|
|
|
177
174
|
const objectPropertiesToFlow = (ctx, type, typeName, selections) => {
|
|
178
175
|
return selections.flatMap(selection => {
|
|
179
176
|
switch (selection.kind) {
|
|
180
|
-
case
|
|
177
|
+
case "InlineFragment":
|
|
181
178
|
{
|
|
182
179
|
var _selection$typeCondit, _selection$typeCondit2;
|
|
183
180
|
|
|
@@ -190,7 +187,7 @@ const objectPropertiesToFlow = (ctx, type, typeName, selections) => {
|
|
|
190
187
|
return objectPropertiesToFlow(ctx, ctx.schema.typesByName[newTypeName], newTypeName, selection.selectionSet.selections);
|
|
191
188
|
}
|
|
192
189
|
|
|
193
|
-
case
|
|
190
|
+
case "FragmentSpread":
|
|
194
191
|
if (!ctx.fragments[selection.name.value]) {
|
|
195
192
|
ctx.errors.push(`No fragment named '${selection.name.value}'. Did you forget to include it in the template literal?`);
|
|
196
193
|
return [babelTypes.tsPropertySignature(babelTypes.identifier(selection.name.value), babelTypes.tsTypeAnnotation(babelTypes.tsTypeReference(babelTypes.identifier(`UNKNOWN_FRAGMENT`))))];
|
|
@@ -198,11 +195,11 @@ const objectPropertiesToFlow = (ctx, type, typeName, selections) => {
|
|
|
198
195
|
|
|
199
196
|
return objectPropertiesToFlow(ctx, type, typeName, ctx.fragments[selection.name.value].selectionSet.selections);
|
|
200
197
|
|
|
201
|
-
case
|
|
198
|
+
case "Field":
|
|
202
199
|
const name = selection.name.value;
|
|
203
200
|
const alias = selection.alias ? selection.alias.value : name;
|
|
204
201
|
|
|
205
|
-
if (name ===
|
|
202
|
+
if (name === "__typename") {
|
|
206
203
|
return [babelTypes.tsPropertySignature(babelTypes.identifier(alias), babelTypes.tsTypeAnnotation(babelTypes.tsLiteralType(babelTypes.stringLiteral(typeName))))];
|
|
207
204
|
}
|
|
208
205
|
|
|
@@ -217,8 +214,7 @@ const objectPropertiesToFlow = (ctx, type, typeName, selections) => {
|
|
|
217
214
|
}, typeField.type, selection)))))];
|
|
218
215
|
|
|
219
216
|
default:
|
|
220
|
-
ctx.errors.push(
|
|
221
|
-
`Unsupported selection kind '${selection.kind}'`);
|
|
217
|
+
ctx.errors.push(`Unsupported selection kind '${selection.kind}'`);
|
|
222
218
|
return [];
|
|
223
219
|
}
|
|
224
220
|
});
|
|
@@ -227,7 +223,7 @@ const objectPropertiesToFlow = (ctx, type, typeName, selections) => {
|
|
|
227
223
|
exports.objectPropertiesToFlow = objectPropertiesToFlow;
|
|
228
224
|
|
|
229
225
|
const unionOrInterfaceToFlow = (ctx, type, selections) => {
|
|
230
|
-
const allFields = selections.every(selection => selection.kind ===
|
|
226
|
+
const allFields = selections.every(selection => selection.kind === "Field");
|
|
231
227
|
const selectedAttributes = type.possibleTypes.slice().sort((a, b) => {
|
|
232
228
|
return a.name < b.name ? -1 : 1;
|
|
233
229
|
}).map(possible => {
|
|
@@ -242,10 +238,10 @@ const unionOrInterfaceToFlow = (ctx, type, selections) => {
|
|
|
242
238
|
|
|
243
239
|
if (allFields) {
|
|
244
240
|
const sharedAttributes = selectedAttributes[0].attributes.slice();
|
|
245
|
-
const typeNameIndex = selectedAttributes[0].attributes.findIndex(x => x.type ===
|
|
241
|
+
const typeNameIndex = selectedAttributes[0].attributes.findIndex(x => x.type === "TSPropertySignature" && x.key.type === "Identifier" && x.key.name === "__typename");
|
|
246
242
|
|
|
247
243
|
if (typeNameIndex !== -1) {
|
|
248
|
-
sharedAttributes[typeNameIndex] = babelTypes.tsPropertySignature(babelTypes.identifier(
|
|
244
|
+
sharedAttributes[typeNameIndex] = babelTypes.tsPropertySignature(babelTypes.identifier("__typename"), babelTypes.tsTypeAnnotation(babelTypes.tsUnionType(selectedAttributes.map(attrs => attrs.attributes[typeNameIndex].typeAnnotation.typeAnnotation))));
|
|
249
245
|
}
|
|
250
246
|
|
|
251
247
|
return sortedObjectTypeAnnotation(ctx, sharedAttributes);
|
|
@@ -292,7 +288,7 @@ const unionOrInterfaceToFlow = (ctx, type, selections) => {
|
|
|
292
288
|
}) => sortedObjectTypeAnnotation({ ...ctx,
|
|
293
289
|
path: ctx.path.concat([typeName])
|
|
294
290
|
}, attributes)));
|
|
295
|
-
const name = ctx.path.join(
|
|
291
|
+
const name = ctx.path.join("_");
|
|
296
292
|
|
|
297
293
|
if (ctx.allObjectTypes && ctx.path.length > 1) {
|
|
298
294
|
ctx.allObjectTypes[name] = result;
|
|
@@ -305,18 +301,18 @@ const unionOrInterfaceToFlow = (ctx, type, selections) => {
|
|
|
305
301
|
exports.unionOrInterfaceToFlow = unionOrInterfaceToFlow;
|
|
306
302
|
|
|
307
303
|
const unionOrInterfaceSelection = (config, type, possible, selection) => {
|
|
308
|
-
if (selection.kind ===
|
|
304
|
+
if (selection.kind === "Field" && selection.name.value === "__typename") {
|
|
309
305
|
const alias = selection.alias ? selection.alias.value : selection.name.value;
|
|
310
306
|
return [babelTypes.tsPropertySignature(babelTypes.identifier(alias), babelTypes.tsTypeAnnotation(babelTypes.tsLiteralType(babelTypes.stringLiteral(possible.name))))];
|
|
311
307
|
}
|
|
312
308
|
|
|
313
|
-
if (selection.kind ===
|
|
309
|
+
if (selection.kind === "Field" && type.kind !== "UNION") {
|
|
314
310
|
// this is an interface
|
|
315
311
|
const name = selection.name.value;
|
|
316
312
|
const alias = selection.alias ? selection.alias.value : name;
|
|
317
313
|
|
|
318
314
|
if (!type.fieldsByName[name]) {
|
|
319
|
-
config.errors.push(
|
|
315
|
+
config.errors.push("Unknown field: " + name + " on type " + type.name + " for possible " + possible.name);
|
|
320
316
|
return [babelTypes.tsPropertySignature(babelTypes.identifier(alias), babelTypes.tsTypeAnnotation(babelTypes.tsTypeReference(babelTypes.identifier(`UNKNOWN_FIELD`))))];
|
|
321
317
|
}
|
|
322
318
|
|
|
@@ -326,7 +322,7 @@ const unionOrInterfaceSelection = (config, type, possible, selection) => {
|
|
|
326
322
|
}, typeField.type, selection))))];
|
|
327
323
|
}
|
|
328
324
|
|
|
329
|
-
if (selection.kind ===
|
|
325
|
+
if (selection.kind === "FragmentSpread") {
|
|
330
326
|
const fragment = config.fragments[selection.name.value];
|
|
331
327
|
|
|
332
328
|
if (!fragment) {
|
|
@@ -342,10 +338,10 @@ const unionOrInterfaceSelection = (config, type, possible, selection) => {
|
|
|
342
338
|
}
|
|
343
339
|
}
|
|
344
340
|
|
|
345
|
-
if (selection.kind !==
|
|
341
|
+
if (selection.kind !== "InlineFragment") {
|
|
346
342
|
config.errors.push(`union selectors must be inline fragment: found ${selection.kind}`);
|
|
347
343
|
|
|
348
|
-
if (type.kind ===
|
|
344
|
+
if (type.kind === "UNION") {
|
|
349
345
|
config.errors.push(`You're trying to select a field from the union ${type.name},
|
|
350
346
|
but the only field you're allowed to select is "__typename".
|
|
351
347
|
Try using an inline fragment "... on SomeType {}".`);
|