@khanacademy/graphql-flow 3.1.2 → 3.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @khanacademy/graphql-flow
2
2
 
3
+ ## 3.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 96c201e: Add a noComments config option to exclude all comments in the output
8
+ - 7c01b6a: Add a --schema-file graphql argument, and allow exporting a function from the config.js file
9
+ - 96c201e: Add a `noComments` config option to exclude all comments
10
+
11
+ ## 3.1.3
12
+
13
+ ### Patch Changes
14
+
15
+ - a8be4ea: Fix file extension toggling, improve file writing.
16
+
3
17
  ## 3.1.2
4
18
 
5
19
  ### Patch Changes
@@ -3,46 +3,66 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.validateOrThrow = exports.loadConfigFile = exports.getSchemas = exports.findApplicableConfig = void 0;
7
-
8
- var _schemaFromIntrospectionData = require("../schemaFromIntrospectionData");
9
-
6
+ exports.validateOrThrow = exports.parseCliOptions = exports.makeAbsPath = exports.loadConfigFile = exports.getSchemas = exports.getInputFiles = exports.findApplicableConfig = void 0;
10
7
  var _schema = _interopRequireDefault(require("../../schema.json"));
11
-
8
+ var _schemaFromIntrospectionData = require("../schemaFromIntrospectionData");
12
9
  var _fs = _interopRequireDefault(require("fs"));
13
-
14
10
  var _graphql = require("graphql");
15
-
16
11
  var _jsonschema = require("jsonschema");
17
-
18
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
12
+ var _minimist = _interopRequireDefault(require("minimist"));
13
+ var _child_process = require("child_process");
14
+ var _path = _interopRequireDefault(require("path"));
15
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
20
16
  const validateOrThrow = (value, jsonSchema) => {
21
17
  const result = (0, _jsonschema.validate)(value, jsonSchema);
22
-
23
18
  if (!result.valid) {
24
19
  throw new Error(result.errors.map(error => error.toString()).join("\n"));
25
20
  }
26
21
  };
27
-
28
22
  exports.validateOrThrow = validateOrThrow;
29
-
30
- const loadConfigFile = configFile => {
31
- const data = require(configFile);
32
-
23
+ const makeAbsPath = (maybeRelativePath, basePath) => {
24
+ return _path.default.isAbsolute(maybeRelativePath) ? maybeRelativePath : _path.default.join(basePath, maybeRelativePath);
25
+ };
26
+ exports.makeAbsPath = makeAbsPath;
27
+ const loadConfigFile = options => {
28
+ let data = require(options.configFilePath);
29
+ if (typeof data === "function") {
30
+ data = data(options);
31
+ } else {
32
+ if (options.schemaFile) {
33
+ if (Array.isArray(data.generate)) {
34
+ data.generate.forEach(item => {
35
+ item.schemaFilePath = options.schemaFile;
36
+ });
37
+ } else {
38
+ data.generate.schemaFilePath = options.schemaFile;
39
+ }
40
+ }
41
+ }
33
42
  validateOrThrow(data, _schema.default);
34
43
  return data;
35
44
  };
45
+ exports.loadConfigFile = loadConfigFile;
46
+ const findGraphqlTagReferences = root => {
47
+ // NOTE(john): We want to include untracked files here so that we can
48
+ // generate types for them. This is useful for when we have a new file
49
+ // that we want to generate types for, but we haven't committed it yet.
50
+ const response = (0, _child_process.execSync)("git grep -I --word-regexp --name-only --fixed-strings --untracked 'graphql-tag' -- '*.js' '*.jsx' '*.ts' '*.tsx'", {
51
+ encoding: "utf8",
52
+ cwd: root
53
+ });
54
+ return response.trim().split("\n").map(relative => _path.default.join(root, relative));
55
+ };
56
+ const getInputFiles = (options, config) => {
57
+ return options.cliFiles.length ? options.cliFiles : findGraphqlTagReferences(makeAbsPath(config.crawl.root, _path.default.dirname(options.configFilePath)));
58
+ };
59
+
36
60
  /**
37
61
  * Loads a .json 'introspection query response', or a .graphql schema definition.
38
62
  */
39
-
40
-
41
- exports.loadConfigFile = loadConfigFile;
42
-
63
+ exports.getInputFiles = getInputFiles;
43
64
  const getSchemas = schemaFilePath => {
44
65
  const raw = _fs.default.readFileSync(schemaFilePath, "utf8");
45
-
46
66
  if (schemaFilePath.endsWith(".graphql")) {
47
67
  const schemaForValidation = (0, _graphql.buildSchema)(raw);
48
68
  const queryResponse = (0, _graphql.graphqlSync)({
@@ -60,33 +80,43 @@ const getSchemas = schemaFilePath => {
60
80
  return [schemaForValidation, schemaForTypeGeneration];
61
81
  }
62
82
  };
83
+ exports.getSchemas = getSchemas;
84
+ const parseCliOptions = (argv, relativeBase) => {
85
+ const args = (0, _minimist.default)(argv);
86
+ let [configFilePath, ...cliFiles] = args._;
87
+ if (args.h || args.help || !configFilePath) {
88
+ return false;
89
+ }
90
+ configFilePath = makeAbsPath(configFilePath, relativeBase);
91
+ const options = {
92
+ configFilePath,
93
+ cliFiles
94
+ };
95
+ if (args["schema-file"]) {
96
+ options.schemaFile = args["schema-file"];
97
+ }
98
+ return options;
99
+ };
100
+
63
101
  /**
64
102
  * Find the first item of the `config.generate` array where both:
65
103
  * - no item of `exclude` matches
66
104
  * - at least one item of `match` matches
67
105
  */
68
-
69
-
70
- exports.getSchemas = getSchemas;
71
-
106
+ exports.parseCliOptions = parseCliOptions;
72
107
  const findApplicableConfig = (path, configs) => {
73
108
  if (!Array.isArray(configs)) {
74
109
  configs = [configs];
75
110
  }
76
-
77
111
  return configs.find(config => {
78
112
  var _config$exclude;
79
-
80
113
  if ((_config$exclude = config.exclude) !== null && _config$exclude !== void 0 && _config$exclude.some(exclude => new RegExp(exclude).test(path))) {
81
114
  return false;
82
115
  }
83
-
84
116
  if (!config.match) {
85
117
  return true;
86
118
  }
87
-
88
119
  return config.match.some(matcher => new RegExp(matcher).test(path));
89
120
  });
90
121
  };
91
-
92
122
  exports.findApplicableConfig = findApplicableConfig;
package/dist/cli/run.js CHANGED
@@ -1,34 +1,19 @@
1
1
  #!/usr/bin/env node
2
-
3
2
  /* eslint-disable no-console */
4
3
  "use strict";
5
4
 
6
5
  var _generateTypeFiles = require("../generateTypeFiles");
7
-
8
6
  var _parse = require("../parser/parse");
9
-
10
7
  var _resolve = require("../parser/resolve");
11
-
12
8
  var _utils = require("../parser/utils");
13
-
14
9
  var _config = require("./config");
15
-
16
10
  var _apolloUtilities = require("apollo-utilities");
17
-
18
- var _child_process = require("child_process");
19
-
20
11
  var _fs = require("fs");
21
-
22
12
  var _printer = require("graphql/language/printer");
23
-
24
13
  var _validation = require("graphql/validation");
25
-
26
14
  var _path = _interopRequireWildcard(require("path"));
27
-
28
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
29
-
30
- 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; }
31
-
15
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
32
17
  /**
33
18
  * This CLI tool executes the following steps:
34
19
  * 1) parse & validate config file
@@ -39,44 +24,29 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
39
24
  * the DocumentNodes.
40
25
  * 4) generate types for all resolved Queries & Mutations
41
26
  */
42
-
43
27
  /** Step (1) */
44
- const findGraphqlTagReferences = root => {
45
- // NOTE(john): We want to include untracked files here so that we can
46
- // generate types for them. This is useful for when we have a new file
47
- // that we want to generate types for, but we haven't committed it yet.
48
- const response = (0, _child_process.execSync)("git grep -I --word-regexp --name-only --fixed-strings --untracked 'graphql-tag' -- '*.js' '*.jsx' '*.ts' '*.tsx'", {
49
- encoding: "utf8",
50
- cwd: root
51
- });
52
- return response.trim().split("\n").map(relative => _path.default.join(root, relative));
53
- };
54
-
55
- const [_, __, configFilePath, ...cliFiles] = process.argv;
56
-
57
- if (configFilePath === "-h" || configFilePath === "--help" || configFilePath === "help" || !configFilePath) {
28
+ const options = (0, _config.parseCliOptions)(process.argv.slice(2), process.cwd());
29
+ if (options === false) {
58
30
  console.log(`graphql-flow
59
31
 
60
- Usage: graphql-flow [configFile.json] [filesToCrawl...]`);
32
+ Usage: graphql-flow [configFile.json] [filesToCrawl...]
33
+ Options:
34
+ --schema-file: provide a schema file to override the one defined in config`);
61
35
  process.exit(1);
62
36
  }
37
+ const config = (0, _config.loadConfigFile)(options);
38
+ const inputFiles = (0, _config.getInputFiles)(options, config);
63
39
 
64
- const makeAbsPath = (maybeRelativePath, basePath) => {
65
- return _path.default.isAbsolute(maybeRelativePath) ? maybeRelativePath : _path.default.join(basePath, maybeRelativePath);
66
- };
67
-
68
- const absConfigPath = makeAbsPath(configFilePath, process.cwd());
69
- const config = (0, _config.loadConfigFile)(absConfigPath);
70
- const inputFiles = cliFiles.length ? cliFiles : findGraphqlTagReferences(makeAbsPath(config.crawl.root, _path.default.dirname(absConfigPath)));
71
40
  /** Step (2) */
72
41
 
73
42
  const files = (0, _parse.processFiles)(inputFiles, config, f => {
74
43
  const resolvedPath = (0, _utils.getPathWithExtension)(f, config);
75
-
76
44
  if (!resolvedPath) {
77
45
  throw new Error(`Unable to find ${f}`);
78
46
  }
79
-
47
+ if (!(0, _fs.existsSync)(resolvedPath)) {
48
+ return null;
49
+ }
80
50
  return {
81
51
  text: (0, _fs.readFileSync)(resolvedPath, "utf8"),
82
52
  resolvedPath
@@ -85,7 +55,6 @@ const files = (0, _parse.processFiles)(inputFiles, config, f => {
85
55
  let filesHadErrors = false;
86
56
  Object.keys(files).forEach(key => {
87
57
  const file = files[key];
88
-
89
58
  if (file.errors.length) {
90
59
  filesHadErrors = true;
91
60
  console.error(`Errors in ${file.path}`);
@@ -94,19 +63,17 @@ Object.keys(files).forEach(key => {
94
63
  });
95
64
  }
96
65
  });
97
-
98
66
  if (filesHadErrors) {
99
67
  console.error("Aborting");
100
68
  process.exit(1);
101
69
  }
102
- /** Step (3) */
103
70
 
71
+ /** Step (3) */
104
72
 
105
73
  const {
106
74
  resolved,
107
75
  errors
108
76
  } = (0, _resolve.resolveDocuments)(files, config);
109
-
110
77
  if (errors.length) {
111
78
  errors.forEach(error => {
112
79
  console.error(`Resolution error ${error.message} in ${error.loc.path}`);
@@ -114,22 +81,20 @@ if (errors.length) {
114
81
  console.error("Aborting");
115
82
  process.exit(1);
116
83
  }
117
-
118
84
  console.log(Object.keys(resolved).length, "resolved queries");
85
+
119
86
  /** Step (4) */
120
87
 
121
88
  const schemaCache = {};
122
-
123
89
  const getCachedSchemas = schemaFilePath => {
124
90
  if (!schemaCache[schemaFilePath]) {
125
- schemaCache[schemaFilePath] = (0, _config.getSchemas)(makeAbsPath(schemaFilePath, _path.default.dirname(absConfigPath)));
91
+ schemaCache[schemaFilePath] = (0, _config.getSchemas)((0, _config.makeAbsPath)(schemaFilePath, _path.default.dirname(options.configFilePath)));
126
92
  }
127
-
128
93
  return schemaCache[schemaFilePath];
129
94
  };
130
-
131
95
  let validationFailures = 0;
132
96
  const printedOperations = [];
97
+ let outputFiles = {};
133
98
  Object.keys(resolved).forEach(filePathAndLine => {
134
99
  const {
135
100
  document,
@@ -139,35 +104,27 @@ Object.keys(resolved).forEach(filePathAndLine => {
139
104
  kind
140
105
  }) => kind !== "FragmentDefinition");
141
106
  const rawSource = raw.literals[0];
142
- const generateConfig = (0, _config.findApplicableConfig)( // strip off the trailing line number, e.g. `:23`
107
+ const generateConfig = (0, _config.findApplicableConfig)(
108
+ // strip off the trailing line number, e.g. `:23`
143
109
  filePathAndLine.split(":")[0], config.generate);
144
-
145
110
  if (!generateConfig) {
146
111
  return; // no generate config matches, bail
147
112
  }
148
-
149
113
  const withTypeNames = (0, _apolloUtilities.addTypenameToDocument)(document);
150
114
  const printed = (0, _printer.print)(withTypeNames);
151
-
152
115
  if (hasNonFragments && !printedOperations.includes(printed)) {
153
116
  printedOperations.push(printed);
154
117
  }
155
-
156
118
  const pragmaResult = (0, _generateTypeFiles.processPragmas)(generateConfig, config.crawl, rawSource);
157
-
158
119
  if (!pragmaResult.generate) {
159
120
  return;
160
121
  }
161
-
162
122
  if (pragmaResult.strict != null) {
163
123
  generateConfig.strictNullability = pragmaResult.strict;
164
124
  }
165
-
166
125
  const [schemaForValidation, schemaForTypeGeneration] = getCachedSchemas(generateConfig.schemaFilePath);
167
-
168
126
  if (hasNonFragments) {
169
127
  const errors = (0, _validation.validate)(schemaForValidation, withTypeNames);
170
-
171
128
  if (errors.length) {
172
129
  errors.forEach(error => {
173
130
  console.error(`Schema validation found errors for ${raw.loc.path}!`);
@@ -177,9 +134,8 @@ Object.keys(resolved).forEach(filePathAndLine => {
177
134
  });
178
135
  }
179
136
  }
180
-
181
137
  try {
182
- (0, _generateTypeFiles.generateTypeFiles)(raw.loc.path, schemaForTypeGeneration, withTypeNames, generateConfig);
138
+ outputFiles = (0, _generateTypeFiles.generateTypeFiles)(raw.loc.path, schemaForTypeGeneration, withTypeNames, generateConfig, outputFiles);
183
139
  } catch (err) {
184
140
  console.error(`Error while generating operation from ${raw.loc.path}`);
185
141
  console.error(printed);
@@ -188,11 +144,15 @@ Object.keys(resolved).forEach(filePathAndLine => {
188
144
  }
189
145
  });
190
146
 
147
+ /** Step (5) */
148
+
149
+ for (const [fname, content] of Object.entries(outputFiles)) {
150
+ (0, _fs.writeFileSync)(fname, content, "utf8");
151
+ }
191
152
  if (validationFailures) {
192
153
  console.error(`Encountered ${validationFailures} validation failures while printing types.`);
193
154
  process.exit(1);
194
155
  }
195
-
196
156
  if (config.crawl.dumpOperations) {
197
157
  const dumpOperations = config.crawl.dumpOperations;
198
158
  const parent = (0, _path.dirname)(dumpOperations);
package/dist/enums.js CHANGED
@@ -4,44 +4,34 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.scalarTypeToFlow = exports.experimentalEnumTypeToFlow = exports.enumTypeToFlow = exports.builtinScalars = void 0;
7
-
8
7
  var babelTypes = _interopRequireWildcard(require("@babel/types"));
9
-
10
8
  var _utils = require("./utils");
11
-
12
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
-
14
- 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; }
15
-
9
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
10
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
16
11
  /**
17
12
  * Both input & output types can have enums & scalars.
18
13
  */
14
+
19
15
  const experimentalEnumTypeToFlow = (ctx, enumConfig, description) => {
20
- const enumDeclaration = babelTypes.tsEnumDeclaration( // pass id into generic type annotation
16
+ const enumDeclaration = babelTypes.tsEnumDeclaration(
17
+ // pass id into generic type annotation
21
18
  babelTypes.identifier(enumConfig.name), enumConfig.enumValues.map(v => babelTypes.tsEnumMember(babelTypes.identifier(v.name), babelTypes.stringLiteral(v.name))));
22
-
23
19
  if (ctx.experimentalEnumsMap) {
24
20
  ctx.experimentalEnumsMap[enumConfig.name] = enumDeclaration;
25
21
  }
26
-
27
- return (0, _utils.maybeAddDescriptionComment)(description, babelTypes.tsTypeReference(enumDeclaration.id));
22
+ return (0, _utils.maybeAddDescriptionComment)(ctx.noComments ? null : description, babelTypes.tsTypeReference(enumDeclaration.id));
28
23
  };
29
-
30
24
  exports.experimentalEnumTypeToFlow = experimentalEnumTypeToFlow;
31
-
32
25
  const enumTypeToFlow = (ctx, name) => {
33
26
  const enumConfig = ctx.schema.enumsByName[name];
34
27
  let combinedDescription = enumConfig.enumValues.map(n => `- ${n.name}` + (n.description ? "\n\n " + n.description.replace(/\n/g, "\n ") : "")).join("\n");
35
-
36
28
  if (enumConfig.description) {
37
29
  combinedDescription = enumConfig.description + "\n\n" + combinedDescription;
38
30
  }
39
-
40
- return ctx.experimentalEnumsMap ? experimentalEnumTypeToFlow(ctx, enumConfig, combinedDescription) : (0, _utils.maybeAddDescriptionComment)(combinedDescription, babelTypes.tsUnionType(enumConfig.enumValues.map(n => babelTypes.tsLiteralType(babelTypes.stringLiteral(n.name)))));
31
+ return ctx.experimentalEnumsMap ? experimentalEnumTypeToFlow(ctx, enumConfig, combinedDescription) : (0, _utils.maybeAddDescriptionComment)(ctx.noComments ? null : combinedDescription, babelTypes.tsUnionType(enumConfig.enumValues.map(n => babelTypes.tsLiteralType(babelTypes.stringLiteral(n.name)))));
41
32
  };
42
-
43
33
  exports.enumTypeToFlow = enumTypeToFlow;
44
- const builtinScalars = {
34
+ const builtinScalars = exports.builtinScalars = {
45
35
  Boolean: "boolean",
46
36
  String: "string",
47
37
  DateTime: "string",
@@ -50,21 +40,15 @@ const builtinScalars = {
50
40
  Int: "number",
51
41
  Float: "number"
52
42
  };
53
- exports.builtinScalars = builtinScalars;
54
-
55
43
  const scalarTypeToFlow = (ctx, name) => {
56
44
  if (builtinScalars[name]) {
57
45
  return babelTypes.tsTypeReference(babelTypes.identifier(builtinScalars[name]));
58
46
  }
59
-
60
47
  const underlyingType = ctx.scalars[name];
61
-
62
48
  if (underlyingType != null) {
63
49
  return babelTypes.tsTypeReference(babelTypes.identifier(underlyingType));
64
50
  }
65
-
66
51
  ctx.errors.push(`Unexpected scalar '${name}'! Please add it to the "scalars" argument at the callsite of 'generateFlowTypes()'.`);
67
52
  return babelTypes.tsTypeReference(babelTypes.identifier(`UNKNOWN_SCALAR["${name}"]`));
68
53
  };
69
-
70
54
  exports.scalarTypeToFlow = scalarTypeToFlow;