@khanacademy/graphql-flow 3.1.0 → 3.1.1
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/CHANGELOG.md +6 -0
- package/dist/cli/run.js +9 -23
- package/dist/parser/parse.js +6 -5
- package/dist/parser/resolve.js +4 -0
- package/dist/parser/utils.js +13 -10
- package/package.json +1 -1
- package/schema.json +18 -2
- package/src/cli/run.ts +5 -15
- package/src/parser/__test__/utils.test.ts +2 -2
- package/src/parser/parse.ts +9 -6
- package/src/parser/resolve.ts +4 -1
- package/src/parser/utils.ts +11 -14
package/CHANGELOG.md
CHANGED
package/dist/cli/run.js
CHANGED
|
@@ -9,6 +9,8 @@ var _parse = require("../parser/parse");
|
|
|
9
9
|
|
|
10
10
|
var _resolve = require("../parser/resolve");
|
|
11
11
|
|
|
12
|
+
var _utils = require("../parser/utils");
|
|
13
|
+
|
|
12
14
|
var _config = require("./config");
|
|
13
15
|
|
|
14
16
|
var _apolloUtilities = require("apollo-utilities");
|
|
@@ -69,32 +71,16 @@ const inputFiles = cliFiles.length ? cliFiles : findGraphqlTagReferences(makeAbs
|
|
|
69
71
|
/** Step (2) */
|
|
70
72
|
|
|
71
73
|
const files = (0, _parse.processFiles)(inputFiles, config, f => {
|
|
72
|
-
|
|
73
|
-
return (0, _fs.readFileSync)(f, "utf8");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if ((0, _fs.existsSync)(f + ".js")) {
|
|
77
|
-
return {
|
|
78
|
-
text: (0, _fs.readFileSync)(f + ".js", "utf8"),
|
|
79
|
-
resolvedPath: f + ".js"
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if ((0, _fs.existsSync)(f + ".ts")) {
|
|
84
|
-
return {
|
|
85
|
-
text: (0, _fs.readFileSync)(f + ".ts", "utf8"),
|
|
86
|
-
resolvedPath: f + ".ts"
|
|
87
|
-
};
|
|
88
|
-
}
|
|
74
|
+
const resolvedPath = (0, _utils.getPathWithExtension)(f, config);
|
|
89
75
|
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
text: (0, _fs.readFileSync)(f + ".tsx", "utf8"),
|
|
93
|
-
resolvedPath: f + ".tsx"
|
|
94
|
-
};
|
|
76
|
+
if (!resolvedPath) {
|
|
77
|
+
throw new Error(`Unable to find ${f}`);
|
|
95
78
|
}
|
|
96
79
|
|
|
97
|
-
|
|
80
|
+
return {
|
|
81
|
+
text: (0, _fs.readFileSync)(resolvedPath, "utf8"),
|
|
82
|
+
resolvedPath
|
|
83
|
+
};
|
|
98
84
|
});
|
|
99
85
|
let filesHadErrors = false;
|
|
100
86
|
Object.keys(files).forEach(key => {
|
package/dist/parser/parse.js
CHANGED
|
@@ -52,7 +52,7 @@ const listExternalReferences = (file, config) => {
|
|
|
52
52
|
return Object.keys(paths);
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
const processFile = (filePath, contents) => {
|
|
55
|
+
const processFile = (filePath, contents, config) => {
|
|
56
56
|
const dir = _path.default.dirname(filePath);
|
|
57
57
|
|
|
58
58
|
const result = {
|
|
@@ -75,7 +75,7 @@ const processFile = (filePath, contents) => {
|
|
|
75
75
|
var _toplevel$declaration;
|
|
76
76
|
|
|
77
77
|
if (toplevel.type === "ImportDeclaration") {
|
|
78
|
-
const newLocals = getLocals(dir, toplevel, filePath);
|
|
78
|
+
const newLocals = getLocals(dir, toplevel, filePath, config);
|
|
79
79
|
|
|
80
80
|
if (newLocals) {
|
|
81
81
|
Object.keys(newLocals).forEach(k => {
|
|
@@ -297,12 +297,13 @@ const processTemplate = (tpl, result, getTemplate) => {
|
|
|
297
297
|
};
|
|
298
298
|
};
|
|
299
299
|
|
|
300
|
-
const getLocals = (dir, toplevel, myPath) => {
|
|
300
|
+
const getLocals = (dir, toplevel, myPath, config) => {
|
|
301
301
|
if (toplevel.importKind === "type") {
|
|
302
302
|
return null;
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
const
|
|
305
|
+
const fixedPath = (0, _utils.fixPathResolution)(toplevel.source.value, config);
|
|
306
|
+
const importPath = fixedPath.startsWith(".") ? _path.default.resolve(_path.default.join(dir, fixedPath)) : fixedPath;
|
|
306
307
|
const locals = {};
|
|
307
308
|
toplevel.specifiers.forEach(spec => {
|
|
308
309
|
if (spec.type === "ImportDefaultSpecifier") {
|
|
@@ -343,7 +344,7 @@ const processFiles = (filePaths, config, getFileSource) => {
|
|
|
343
344
|
continue;
|
|
344
345
|
}
|
|
345
346
|
|
|
346
|
-
const result = processFile(next, getFileSource(next));
|
|
347
|
+
const result = processFile(next, getFileSource(next), config);
|
|
347
348
|
files[next] = result;
|
|
348
349
|
listExternalReferences(result, config).forEach(path => {
|
|
349
350
|
if (!files[path] && !toProcess.includes(path)) {
|
package/dist/parser/resolve.js
CHANGED
|
@@ -38,6 +38,10 @@ exports.resolveDocuments = resolveDocuments;
|
|
|
38
38
|
const resolveImport = (expr, files, errors, seen, config) => {
|
|
39
39
|
const absPath = (0, _utils.getPathWithExtension)(expr.path, config);
|
|
40
40
|
|
|
41
|
+
if (!absPath) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
if (seen[absPath]) {
|
|
42
46
|
errors.push({
|
|
43
47
|
loc: expr.loc,
|
package/dist/parser/utils.js
CHANGED
|
@@ -3,23 +3,30 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.getPathWithExtension = void 0;
|
|
6
|
+
exports.getPathWithExtension = exports.fixPathResolution = void 0;
|
|
7
7
|
|
|
8
8
|
var _fs = _interopRequireDefault(require("fs"));
|
|
9
9
|
|
|
10
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
// Process the path so that we can handle aliases.
|
|
12
|
+
const fixPathResolution = (path, config) => {
|
|
14
13
|
if (config.alias) {
|
|
15
14
|
for (const {
|
|
16
15
|
find,
|
|
17
16
|
replacement
|
|
18
17
|
} of config.alias) {
|
|
19
|
-
|
|
18
|
+
path = path.replace(find, replacement);
|
|
20
19
|
}
|
|
21
20
|
}
|
|
22
21
|
|
|
22
|
+
return path;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
exports.fixPathResolution = fixPathResolution;
|
|
26
|
+
|
|
27
|
+
const getPathWithExtension = (pathWithoutExtension, config) => {
|
|
28
|
+
pathWithoutExtension = fixPathResolution(pathWithoutExtension, config);
|
|
29
|
+
|
|
23
30
|
if (/\.(less|css|png|gif|jpg|jpeg|js|jsx|ts|tsx|mjs)$/.test(pathWithoutExtension)) {
|
|
24
31
|
return pathWithoutExtension;
|
|
25
32
|
}
|
|
@@ -38,13 +45,9 @@ const getPathWithExtension = (pathWithoutExtension, config) => {
|
|
|
38
45
|
|
|
39
46
|
if (_fs.default.existsSync(pathWithoutExtension + ".ts")) {
|
|
40
47
|
return pathWithoutExtension + ".ts";
|
|
41
|
-
}
|
|
42
|
-
// have a file that doesn't exist. This will happen when we delete all of
|
|
43
|
-
// the type files before re-running graphql-flow again. We want to ensure
|
|
44
|
-
// that we don't error out in this case.
|
|
45
|
-
|
|
48
|
+
}
|
|
46
49
|
|
|
47
|
-
return
|
|
50
|
+
return null;
|
|
48
51
|
};
|
|
49
52
|
|
|
50
53
|
exports.getPathWithExtension = getPathWithExtension;
|
package/package.json
CHANGED
package/schema.json
CHANGED
|
@@ -91,7 +91,23 @@
|
|
|
91
91
|
"generate": {"oneOf": [
|
|
92
92
|
{"$ref": "#/definitions/GenerateConfig"},
|
|
93
93
|
{"type": "array", "items": {"$ref": "#/definitions/GenerateConfig"}}
|
|
94
|
-
]}
|
|
94
|
+
]},
|
|
95
|
+
"alias": {
|
|
96
|
+
"type": "array",
|
|
97
|
+
"items": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"additionalProperties": false,
|
|
100
|
+
"properties": {
|
|
101
|
+
"find": {
|
|
102
|
+
"type": ["string", "object"]
|
|
103
|
+
},
|
|
104
|
+
"replacement": {
|
|
105
|
+
"type": "string"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"required": [ "find", "replacement" ]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
95
111
|
},
|
|
96
112
|
"required": [ "crawl", "generate" ]
|
|
97
|
-
}
|
|
113
|
+
}
|
package/src/cli/run.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {GraphQLSchema} from "graphql/type/schema";
|
|
|
6
6
|
import {generateTypeFiles, processPragmas} from "../generateTypeFiles";
|
|
7
7
|
import {processFiles} from "../parser/parse";
|
|
8
8
|
import {resolveDocuments} from "../parser/resolve";
|
|
9
|
+
import {getPathWithExtension} from "../parser/utils";
|
|
9
10
|
import {findApplicableConfig, getSchemas, loadConfigFile} from "./config";
|
|
10
11
|
|
|
11
12
|
import {addTypenameToDocument} from "apollo-utilities";
|
|
@@ -81,22 +82,11 @@ const inputFiles = cliFiles.length
|
|
|
81
82
|
/** Step (2) */
|
|
82
83
|
|
|
83
84
|
const files = processFiles(inputFiles, config, (f) => {
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
const resolvedPath = getPathWithExtension(f, config);
|
|
86
|
+
if (!resolvedPath) {
|
|
87
|
+
throw new Error(`Unable to find ${f}`);
|
|
86
88
|
}
|
|
87
|
-
|
|
88
|
-
return {text: readFileSync(f + ".js", "utf8"), resolvedPath: f + ".js"};
|
|
89
|
-
}
|
|
90
|
-
if (existsSync(f + ".ts")) {
|
|
91
|
-
return {text: readFileSync(f + ".ts", "utf8"), resolvedPath: f + ".ts"};
|
|
92
|
-
}
|
|
93
|
-
if (existsSync(f + ".tsx")) {
|
|
94
|
-
return {
|
|
95
|
-
text: readFileSync(f + ".tsx", "utf8"),
|
|
96
|
-
resolvedPath: f + ".tsx",
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
throw new Error(`Unable to find ${f}`);
|
|
89
|
+
return {text: readFileSync(resolvedPath, "utf8"), resolvedPath};
|
|
100
90
|
});
|
|
101
91
|
|
|
102
92
|
let filesHadErrors = false;
|
|
@@ -50,7 +50,7 @@ describe("getPathWithExtension", () => {
|
|
|
50
50
|
expect(result).toBe("/path/to/file.js");
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
it("returns
|
|
53
|
+
it("returns null if no file is found", () => {
|
|
54
54
|
// Arrange
|
|
55
55
|
jest.spyOn(fs, "existsSync").mockImplementation((path) => false);
|
|
56
56
|
|
|
@@ -58,7 +58,7 @@ describe("getPathWithExtension", () => {
|
|
|
58
58
|
const result = getPathWithExtension("/path/to/file", config);
|
|
59
59
|
|
|
60
60
|
// Assert
|
|
61
|
-
expect(result).toBe(
|
|
61
|
+
expect(result).toBe(null);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
it("maps aliases to their correct value", () => {
|
package/src/parser/parse.ts
CHANGED
|
@@ -11,7 +11,7 @@ import traverse from "@babel/traverse";
|
|
|
11
11
|
|
|
12
12
|
import path from "path";
|
|
13
13
|
|
|
14
|
-
import {getPathWithExtension} from "./utils";
|
|
14
|
+
import {fixPathResolution, getPathWithExtension} from "./utils";
|
|
15
15
|
import {Config} from "../types";
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -152,6 +152,7 @@ export const processFile = (
|
|
|
152
152
|
text: string;
|
|
153
153
|
resolvedPath: string;
|
|
154
154
|
},
|
|
155
|
+
config: Config,
|
|
155
156
|
): FileResult => {
|
|
156
157
|
const dir = path.dirname(filePath);
|
|
157
158
|
const result: FileResult = {
|
|
@@ -177,7 +178,7 @@ export const processFile = (
|
|
|
177
178
|
|
|
178
179
|
ast.program.body.forEach((toplevel) => {
|
|
179
180
|
if (toplevel.type === "ImportDeclaration") {
|
|
180
|
-
const newLocals = getLocals(dir, toplevel, filePath);
|
|
181
|
+
const newLocals = getLocals(dir, toplevel, filePath, config);
|
|
181
182
|
if (newLocals) {
|
|
182
183
|
Object.keys(newLocals).forEach((k) => {
|
|
183
184
|
const local = newLocals[k];
|
|
@@ -386,6 +387,7 @@ const getLocals = (
|
|
|
386
387
|
dir: string,
|
|
387
388
|
toplevel: ImportDeclaration,
|
|
388
389
|
myPath: string,
|
|
390
|
+
config: Config,
|
|
389
391
|
):
|
|
390
392
|
| {
|
|
391
393
|
[key: string]: Import;
|
|
@@ -395,9 +397,10 @@ const getLocals = (
|
|
|
395
397
|
if (toplevel.importKind === "type") {
|
|
396
398
|
return null;
|
|
397
399
|
}
|
|
398
|
-
const
|
|
399
|
-
|
|
400
|
-
|
|
400
|
+
const fixedPath = fixPathResolution(toplevel.source.value, config);
|
|
401
|
+
const importPath = fixedPath.startsWith(".")
|
|
402
|
+
? path.resolve(path.join(dir, fixedPath))
|
|
403
|
+
: fixedPath;
|
|
401
404
|
const locals: Record<string, any> = {};
|
|
402
405
|
toplevel.specifiers.forEach((spec) => {
|
|
403
406
|
if (spec.type === "ImportDefaultSpecifier") {
|
|
@@ -439,7 +442,7 @@ export const processFiles = (
|
|
|
439
442
|
if (!next || files[next]) {
|
|
440
443
|
continue;
|
|
441
444
|
}
|
|
442
|
-
const result = processFile(next, getFileSource(next));
|
|
445
|
+
const result = processFile(next, getFileSource(next), config);
|
|
443
446
|
files[next] = result;
|
|
444
447
|
listExternalReferences(result, config).forEach((path) => {
|
|
445
448
|
if (!files[path] && !toProcess.includes(path)) {
|
package/src/parser/resolve.ts
CHANGED
|
@@ -51,7 +51,10 @@ const resolveImport = (
|
|
|
51
51
|
},
|
|
52
52
|
config: Config,
|
|
53
53
|
): Document | null | undefined => {
|
|
54
|
-
const absPath
|
|
54
|
+
const absPath = getPathWithExtension(expr.path, config);
|
|
55
|
+
if (!absPath) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
55
58
|
if (seen[absPath]) {
|
|
56
59
|
errors.push({
|
|
57
60
|
loc: expr.loc,
|
package/src/parser/utils.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import {Config} from "../types";
|
|
3
3
|
|
|
4
|
-
export const
|
|
5
|
-
pathWithoutExtension: string,
|
|
6
|
-
config: Config,
|
|
7
|
-
): string => {
|
|
8
|
-
// Process the path so that we can handle aliases.
|
|
4
|
+
export const fixPathResolution = (path: string, config: Config) => {
|
|
9
5
|
if (config.alias) {
|
|
10
6
|
for (const {find, replacement} of config.alias) {
|
|
11
|
-
|
|
12
|
-
find,
|
|
13
|
-
replacement,
|
|
14
|
-
);
|
|
7
|
+
path = path.replace(find, replacement);
|
|
15
8
|
}
|
|
16
9
|
}
|
|
10
|
+
return path;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const getPathWithExtension = (
|
|
14
|
+
pathWithoutExtension: string,
|
|
15
|
+
config: Config,
|
|
16
|
+
) => {
|
|
17
|
+
pathWithoutExtension = fixPathResolution(pathWithoutExtension, config);
|
|
17
18
|
if (
|
|
18
19
|
/\.(less|css|png|gif|jpg|jpeg|js|jsx|ts|tsx|mjs)$/.test(
|
|
19
20
|
pathWithoutExtension,
|
|
@@ -33,9 +34,5 @@ export const getPathWithExtension = (
|
|
|
33
34
|
if (fs.existsSync(pathWithoutExtension + ".ts")) {
|
|
34
35
|
return pathWithoutExtension + ".ts";
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
-
// have a file that doesn't exist. This will happen when we delete all of
|
|
38
|
-
// the type files before re-running graphql-flow again. We want to ensure
|
|
39
|
-
// that we don't error out in this case.
|
|
40
|
-
return "";
|
|
37
|
+
return null;
|
|
41
38
|
};
|