@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.
Files changed (40) hide show
  1. package/.flowconfig +1 -0
  2. package/.github/workflows/changeset-release.yml +3 -17
  3. package/.github/workflows/pr-checks.yml +15 -10
  4. package/CHANGELOG.md +19 -0
  5. package/Readme.md +36 -1
  6. package/dist/cli/config.js +102 -15
  7. package/dist/cli/config.js.flow +131 -29
  8. package/dist/cli/config.js.map +1 -1
  9. package/dist/cli/run.js +45 -11
  10. package/dist/cli/run.js.flow +45 -7
  11. package/dist/cli/run.js.map +1 -1
  12. package/dist/cli/utils.js +21 -0
  13. package/dist/cli/utils.js.flow +14 -0
  14. package/dist/cli/utils.js.map +1 -0
  15. package/dist/enums.js +15 -2
  16. package/dist/enums.js.flow +38 -9
  17. package/dist/enums.js.map +1 -1
  18. package/dist/generateTypeFiles.js +30 -7
  19. package/dist/generateTypeFiles.js.flow +68 -38
  20. package/dist/generateTypeFiles.js.map +1 -1
  21. package/dist/index.js +18 -12
  22. package/dist/index.js.flow +27 -11
  23. package/dist/index.js.map +1 -1
  24. package/dist/types.js.flow +3 -0
  25. package/flow-typed/npm/@babel/types_vx.x.x.js +17 -3
  26. package/package.json +1 -1
  27. package/src/__test__/generateTypeFileContents.test.js +52 -0
  28. package/src/cli/__test__/config.test.js +94 -0
  29. package/src/cli/__test__/utils.test.js +19 -0
  30. package/src/cli/config.js +131 -29
  31. package/src/cli/run.js +45 -7
  32. package/src/cli/utils.js +14 -0
  33. package/src/enums.js +38 -9
  34. package/src/generateTypeFiles.js +68 -38
  35. package/src/index.js +27 -11
  36. package/src/types.js +3 -0
  37. package/.github/actions/filter-files/action.yml +0 -37
  38. package/.github/actions/full-or-limited/action.yml +0 -27
  39. package/.github/actions/json-args/action.yml +0 -32
  40. package/.github/actions/setup/action.yml +0 -28
package/dist/cli/run.js CHANGED
@@ -21,9 +21,13 @@ var _printer = require("graphql/language/printer");
21
21
 
22
22
  var _validation = require("graphql/validation");
23
23
 
24
- var _path = _interopRequireDefault(require("path"));
24
+ var _path = _interopRequireWildcard(require("path"));
25
25
 
26
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
+ var _utils = require("./utils");
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; }
27
31
 
28
32
  // eslint-disable-line flowtype-errors/uncovered
29
33
 
@@ -56,7 +60,17 @@ Usage: graphql-flow [configFile.json] [filesToCrawl...]`);
56
60
  process.exit(1); // eslint-disable-line flowtype-errors/uncovered
57
61
  }
58
62
 
59
- const config = (0, _config.loadConfigFile)(configFile);
63
+ const config = (0, _config.loadConfigFile)(configFile); // find file paths ending with "graphql-flow.config.json"
64
+
65
+ const subConfigsQuery = () => (0, _child_process.execSync)('git ls-files "*graphql-flow.config.json"', {
66
+ encoding: 'utf8',
67
+ cwd: process.cwd()
68
+ });
69
+
70
+ const subConfigMap = (0, _config.loadDirConfigFiles)(subConfigsQuery(), {
71
+ config,
72
+ path: configFile
73
+ });
60
74
  const [schemaForValidation, schemaForTypeGeneration] = (0, _config.getSchemas)(config.schemaFilePath);
61
75
  const inputFiles = cliFiles.length ? cliFiles : findGraphqlTagReferences(process.cwd());
62
76
  /** Step (2) */
@@ -109,30 +123,41 @@ console.log(Object.keys(resolved).length, 'resolved queries');
109
123
  /** Step (4) */
110
124
 
111
125
  let validationFailures = 0;
126
+ const printedOperations = [];
112
127
  Object.keys(resolved).forEach(k => {
113
128
  const {
114
129
  document,
115
130
  raw
116
131
  } = resolved[k];
132
+ let fileConfig = config;
133
+ const closestConfigPath = (0, _utils.longestMatchingPath)(raw.loc.path, Object.keys(subConfigMap)); // get longest match in the case of nested subconfigs
117
134
 
118
- if (config.excludes.some(rx => rx.test(raw.loc.path))) {
135
+ if (closestConfigPath) {
136
+ fileConfig = subConfigMap[closestConfigPath];
137
+ }
138
+
139
+ if (fileConfig.excludes.some(rx => rx.test(raw.loc.path))) {
119
140
  return; // skip
120
141
  }
121
142
 
122
143
  const hasNonFragments = document.definitions.some(({
123
144
  kind
124
145
  }) => kind !== 'FragmentDefinition');
125
- const rawSource = raw.literals[0];
126
- const processedOptions = (0, _generateTypeFiles.processPragmas)(config.options, rawSource);
127
-
128
- if (!processedOptions) {
129
- return;
130
- } // eslint-disable-next-line flowtype-errors/uncovered
131
-
146
+ const rawSource = raw.literals[0]; // eslint-disable-next-line flowtype-errors/uncovered
132
147
 
133
148
  const withTypeNames = (0, _apolloUtilities.addTypenameToDocument)(document);
134
149
  const printed = (0, _printer.print)(withTypeNames);
135
150
 
151
+ if (hasNonFragments && !printedOperations.includes(printed)) {
152
+ printedOperations.push(printed);
153
+ }
154
+
155
+ const processedOptions = (0, _generateTypeFiles.processPragmas)(fileConfig.options, rawSource);
156
+
157
+ if (!processedOptions) {
158
+ return;
159
+ }
160
+
136
161
  if (hasNonFragments) {
137
162
  /* eslint-disable flowtype-errors/uncovered */
138
163
  const errors = (0, _validation.validate)(schemaForValidation, withTypeNames);
@@ -166,4 +191,13 @@ if (validationFailures) {
166
191
 
167
192
  process.exit(1);
168
193
  }
194
+
195
+ if (config.dumpOperations) {
196
+ const dumpOperations = config.dumpOperations;
197
+ const parent = (0, _path.dirname)(dumpOperations);
198
+ (0, _fs.mkdirSync)(parent, {
199
+ recursive: true
200
+ });
201
+ (0, _fs.writeFileSync)(dumpOperations, JSON.stringify(printedOperations.sort(), null, 2));
202
+ }
169
203
  //# sourceMappingURL=run.js.map
@@ -4,16 +4,18 @@
4
4
  import {generateTypeFiles, processPragmas} from '../generateTypeFiles';
5
5
  import {processFiles} from '../parser/parse';
6
6
  import {resolveDocuments} from '../parser/resolve';
7
- import {getSchemas, loadConfigFile} from './config';
7
+ import {loadDirConfigFiles, getSchemas, loadConfigFile} from './config';
8
8
 
9
9
  import {addTypenameToDocument} from 'apollo-utilities'; // eslint-disable-line flowtype-errors/uncovered
10
10
 
11
11
  import {execSync} from 'child_process';
12
- import {existsSync, readFileSync} from 'fs';
12
+ import {existsSync, mkdirSync, readFileSync, writeFileSync} from 'fs';
13
13
  import {type DocumentNode} from 'graphql';
14
14
  import {print} from 'graphql/language/printer';
15
15
  import {validate} from 'graphql/validation';
16
16
  import path from 'path';
17
+ import {dirname} from 'path';
18
+ import {longestMatchingPath} from './utils';
17
19
 
18
20
  /**
19
21
  * This CLI tool executes the following steps:
@@ -58,6 +60,17 @@ Usage: graphql-flow [configFile.json] [filesToCrawl...]`);
58
60
 
59
61
  const config = loadConfigFile(configFile);
60
62
 
63
+ // find file paths ending with "graphql-flow.config.json"
64
+ const subConfigsQuery = () =>
65
+ execSync('git ls-files "*graphql-flow.config.json"', {
66
+ encoding: 'utf8',
67
+ cwd: process.cwd(),
68
+ });
69
+ const subConfigMap = loadDirConfigFiles(subConfigsQuery(), {
70
+ config,
71
+ path: configFile,
72
+ });
73
+
61
74
  const [schemaForValidation, schemaForTypeGeneration] = getSchemas(
62
75
  config.schemaFilePath,
63
76
  );
@@ -111,24 +124,39 @@ console.log(Object.keys(resolved).length, 'resolved queries');
111
124
  /** Step (4) */
112
125
 
113
126
  let validationFailures: number = 0;
127
+ const printedOperations: Array<string> = [];
114
128
 
115
129
  Object.keys(resolved).forEach((k) => {
116
130
  const {document, raw} = resolved[k];
117
- if (config.excludes.some((rx) => rx.test(raw.loc.path))) {
131
+
132
+ let fileConfig = config;
133
+ const closestConfigPath = longestMatchingPath(
134
+ raw.loc.path,
135
+ Object.keys(subConfigMap),
136
+ ); // get longest match in the case of nested subconfigs
137
+ if (closestConfigPath) {
138
+ fileConfig = subConfigMap[closestConfigPath];
139
+ }
140
+
141
+ if (fileConfig.excludes.some((rx) => rx.test(raw.loc.path))) {
118
142
  return; // skip
119
143
  }
120
144
  const hasNonFragments = document.definitions.some(
121
145
  ({kind}) => kind !== 'FragmentDefinition',
122
146
  );
123
147
  const rawSource: string = raw.literals[0];
124
- const processedOptions = processPragmas(config.options, rawSource);
125
- if (!processedOptions) {
126
- return;
127
- }
128
148
 
129
149
  // eslint-disable-next-line flowtype-errors/uncovered
130
150
  const withTypeNames: DocumentNode = addTypenameToDocument(document);
131
151
  const printed = print(withTypeNames);
152
+ if (hasNonFragments && !printedOperations.includes(printed)) {
153
+ printedOperations.push(printed);
154
+ }
155
+
156
+ const processedOptions = processPragmas(fileConfig.options, rawSource);
157
+ if (!processedOptions) {
158
+ return;
159
+ }
132
160
 
133
161
  if (hasNonFragments) {
134
162
  /* eslint-disable flowtype-errors/uncovered */
@@ -171,3 +199,13 @@ if (validationFailures) {
171
199
  // eslint-disable-next-line flowtype-errors/uncovered
172
200
  process.exit(1);
173
201
  }
202
+
203
+ if (config.dumpOperations) {
204
+ const dumpOperations = config.dumpOperations;
205
+ const parent = dirname(dumpOperations);
206
+ mkdirSync(parent, {recursive: true});
207
+ writeFileSync(
208
+ dumpOperations,
209
+ JSON.stringify(printedOperations.sort(), null, 2),
210
+ );
211
+ }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/run.js"],"names":["findGraphqlTagReferences","root","response","encoding","cwd","trim","split","map","relative","path","join","_","__","configFile","cliFiles","process","argv","console","log","exit","config","schemaForValidation","schemaForTypeGeneration","schemaFilePath","inputFiles","length","files","f","Error","filesHadErrors","Object","keys","forEach","key","file","errors","error","message","resolved","loc","validationFailures","k","document","raw","excludes","some","rx","test","hasNonFragments","definitions","kind","rawSource","literals","processedOptions","options","withTypeNames","printed","err"],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// @flow\n/* eslint-disable no-console */\nimport {generateTypeFiles, processPragmas} from '../generateTypeFiles';\nimport {processFiles} from '../parser/parse';\nimport {resolveDocuments} from '../parser/resolve';\nimport {getSchemas, loadConfigFile} from './config';\n\nimport {addTypenameToDocument} from 'apollo-utilities'; // eslint-disable-line flowtype-errors/uncovered\n\nimport {execSync} from 'child_process';\nimport {existsSync, readFileSync} from 'fs';\nimport {type DocumentNode} from 'graphql';\nimport {print} from 'graphql/language/printer';\nimport {validate} from 'graphql/validation';\nimport path from 'path';\n\n/**\n * This CLI tool executes the following steps:\n * 1) process options\n * 2) crawl files to find all operations and fragments, with\n * tagged template literals and expressions.\n * 3) resolve the found operations, passing the literals and\n * fragments into the `graphql-tag` function to produce\n * the DocumentNodes.\n * 4) generate types for all resolved Queries & Mutations\n */\n\n/** Step (1) */\n\nconst findGraphqlTagReferences = (root: string): Array<string> => {\n const response = execSync(\n \"git grep -I --word-regexp --name-only --fixed-strings 'graphql-tag' -- '*.js' '*.jsx'\",\n {\n encoding: 'utf8',\n cwd: root,\n },\n );\n return response\n .trim()\n .split('\\n')\n .map((relative) => path.join(root, relative));\n};\n\nconst [_, __, configFile, ...cliFiles] = process.argv;\n\nif (\n configFile === '-h' ||\n configFile === '--help' ||\n configFile === 'help' ||\n !configFile\n) {\n console.log(`graphql-flow\n\nUsage: graphql-flow [configFile.json] [filesToCrawl...]`);\n process.exit(1); // eslint-disable-line flowtype-errors/uncovered\n}\n\nconst config = loadConfigFile(configFile);\n\nconst [schemaForValidation, schemaForTypeGeneration] = getSchemas(\n config.schemaFilePath,\n);\n\nconst inputFiles = cliFiles.length\n ? cliFiles\n : findGraphqlTagReferences(process.cwd());\n\n/** Step (2) */\n\nconst files = processFiles(inputFiles, (f) => {\n if (existsSync(f)) {\n return readFileSync(f, 'utf8');\n }\n if (existsSync(f + '.js')) {\n return readFileSync(f + '.js', 'utf8');\n }\n throw new Error(`Unable to find ${f}`);\n});\n\nlet filesHadErrors = false;\nObject.keys(files).forEach((key) => {\n const file = files[key];\n if (file.errors.length) {\n filesHadErrors = true;\n console.error(`Errors in ${file.path}`);\n file.errors.forEach((error) => {\n console.error(` - ${error.message}`);\n });\n }\n});\n\nif (filesHadErrors) {\n console.error('Aborting');\n process.exit(1); // eslint-disable-line flowtype-errors/uncovered\n}\n\n/** Step (3) */\n\nconst {resolved, errors} = resolveDocuments(files);\nif (errors.length) {\n errors.forEach((error) => {\n console.error(`Resolution error ${error.message} in ${error.loc.path}`);\n });\n console.error('Aborting');\n process.exit(1); // eslint-disable-line flowtype-errors/uncovered\n}\n\nconsole.log(Object.keys(resolved).length, 'resolved queries');\n\n/** Step (4) */\n\nlet validationFailures: number = 0;\n\nObject.keys(resolved).forEach((k) => {\n const {document, raw} = resolved[k];\n if (config.excludes.some((rx) => rx.test(raw.loc.path))) {\n return; // skip\n }\n const hasNonFragments = document.definitions.some(\n ({kind}) => kind !== 'FragmentDefinition',\n );\n const rawSource: string = raw.literals[0];\n const processedOptions = processPragmas(config.options, rawSource);\n if (!processedOptions) {\n return;\n }\n\n // eslint-disable-next-line flowtype-errors/uncovered\n const withTypeNames: DocumentNode = addTypenameToDocument(document);\n const printed = print(withTypeNames);\n\n if (hasNonFragments) {\n /* eslint-disable flowtype-errors/uncovered */\n const errors = validate(schemaForValidation, withTypeNames);\n /* eslint-disable flowtype-errors/uncovered */\n if (errors.length) {\n errors.forEach((error) => {\n console.error(\n `Schema validation found errors for ${raw.loc.path}!`,\n );\n console.error(printed);\n console.error(error);\n validationFailures++;\n });\n }\n /* eslint-enable flowtype-errors/uncovered */\n }\n\n try {\n generateTypeFiles(\n raw.loc.path,\n schemaForTypeGeneration,\n withTypeNames,\n processedOptions,\n );\n // eslint-disable-next-line flowtype-errors/uncovered\n } catch (err) {\n console.error(`Error while generating operation from ${raw.loc.path}`);\n console.error(printed);\n // eslint-disable-next-line flowtype-errors/uncovered\n console.error(err);\n validationFailures++;\n }\n});\n\nif (validationFailures) {\n console.error(\n `Encountered ${validationFailures} validation failures while printing types.`,\n );\n // eslint-disable-next-line flowtype-errors/uncovered\n process.exit(1);\n}\n"],"file":"run.js"}
1
+ {"version":3,"sources":["../../src/cli/run.js"],"names":["findGraphqlTagReferences","root","response","encoding","cwd","trim","split","map","relative","path","join","_","__","configFile","cliFiles","process","argv","console","log","exit","config","subConfigsQuery","subConfigMap","schemaForValidation","schemaForTypeGeneration","schemaFilePath","inputFiles","length","files","f","Error","filesHadErrors","Object","keys","forEach","key","file","errors","error","message","resolved","loc","validationFailures","printedOperations","k","document","raw","fileConfig","closestConfigPath","excludes","some","rx","test","hasNonFragments","definitions","kind","rawSource","literals","withTypeNames","printed","includes","push","processedOptions","options","err","dumpOperations","parent","recursive","JSON","stringify","sort"],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// @flow\n/* eslint-disable no-console */\nimport {generateTypeFiles, processPragmas} from '../generateTypeFiles';\nimport {processFiles} from '../parser/parse';\nimport {resolveDocuments} from '../parser/resolve';\nimport {loadDirConfigFiles, getSchemas, loadConfigFile} from './config';\n\nimport {addTypenameToDocument} from 'apollo-utilities'; // eslint-disable-line flowtype-errors/uncovered\n\nimport {execSync} from 'child_process';\nimport {existsSync, mkdirSync, readFileSync, writeFileSync} from 'fs';\nimport {type DocumentNode} from 'graphql';\nimport {print} from 'graphql/language/printer';\nimport {validate} from 'graphql/validation';\nimport path from 'path';\nimport {dirname} from 'path';\nimport {longestMatchingPath} from './utils';\n\n/**\n * This CLI tool executes the following steps:\n * 1) process options\n * 2) crawl files to find all operations and fragments, with\n * tagged template literals and expressions.\n * 3) resolve the found operations, passing the literals and\n * fragments into the `graphql-tag` function to produce\n * the DocumentNodes.\n * 4) generate types for all resolved Queries & Mutations\n */\n\n/** Step (1) */\n\nconst findGraphqlTagReferences = (root: string): Array<string> => {\n const response = execSync(\n \"git grep -I --word-regexp --name-only --fixed-strings 'graphql-tag' -- '*.js' '*.jsx'\",\n {\n encoding: 'utf8',\n cwd: root,\n },\n );\n return response\n .trim()\n .split('\\n')\n .map((relative) => path.join(root, relative));\n};\n\nconst [_, __, configFile, ...cliFiles] = process.argv;\n\nif (\n configFile === '-h' ||\n configFile === '--help' ||\n configFile === 'help' ||\n !configFile\n) {\n console.log(`graphql-flow\n\nUsage: graphql-flow [configFile.json] [filesToCrawl...]`);\n process.exit(1); // eslint-disable-line flowtype-errors/uncovered\n}\n\nconst config = loadConfigFile(configFile);\n\n// find file paths ending with \"graphql-flow.config.json\"\nconst subConfigsQuery = () =>\n execSync('git ls-files \"*graphql-flow.config.json\"', {\n encoding: 'utf8',\n cwd: process.cwd(),\n });\nconst subConfigMap = loadDirConfigFiles(subConfigsQuery(), {\n config,\n path: configFile,\n});\n\nconst [schemaForValidation, schemaForTypeGeneration] = getSchemas(\n config.schemaFilePath,\n);\n\nconst inputFiles = cliFiles.length\n ? cliFiles\n : findGraphqlTagReferences(process.cwd());\n\n/** Step (2) */\n\nconst files = processFiles(inputFiles, (f) => {\n if (existsSync(f)) {\n return readFileSync(f, 'utf8');\n }\n if (existsSync(f + '.js')) {\n return readFileSync(f + '.js', 'utf8');\n }\n throw new Error(`Unable to find ${f}`);\n});\n\nlet filesHadErrors = false;\nObject.keys(files).forEach((key) => {\n const file = files[key];\n if (file.errors.length) {\n filesHadErrors = true;\n console.error(`Errors in ${file.path}`);\n file.errors.forEach((error) => {\n console.error(` - ${error.message}`);\n });\n }\n});\n\nif (filesHadErrors) {\n console.error('Aborting');\n process.exit(1); // eslint-disable-line flowtype-errors/uncovered\n}\n\n/** Step (3) */\n\nconst {resolved, errors} = resolveDocuments(files);\nif (errors.length) {\n errors.forEach((error) => {\n console.error(`Resolution error ${error.message} in ${error.loc.path}`);\n });\n console.error('Aborting');\n process.exit(1); // eslint-disable-line flowtype-errors/uncovered\n}\n\nconsole.log(Object.keys(resolved).length, 'resolved queries');\n\n/** Step (4) */\n\nlet validationFailures: number = 0;\nconst printedOperations: Array<string> = [];\n\nObject.keys(resolved).forEach((k) => {\n const {document, raw} = resolved[k];\n\n let fileConfig = config;\n const closestConfigPath = longestMatchingPath(\n raw.loc.path,\n Object.keys(subConfigMap),\n ); // get longest match in the case of nested subconfigs\n if (closestConfigPath) {\n fileConfig = subConfigMap[closestConfigPath];\n }\n\n if (fileConfig.excludes.some((rx) => rx.test(raw.loc.path))) {\n return; // skip\n }\n const hasNonFragments = document.definitions.some(\n ({kind}) => kind !== 'FragmentDefinition',\n );\n const rawSource: string = raw.literals[0];\n\n // eslint-disable-next-line flowtype-errors/uncovered\n const withTypeNames: DocumentNode = addTypenameToDocument(document);\n const printed = print(withTypeNames);\n if (hasNonFragments && !printedOperations.includes(printed)) {\n printedOperations.push(printed);\n }\n\n const processedOptions = processPragmas(fileConfig.options, rawSource);\n if (!processedOptions) {\n return;\n }\n\n if (hasNonFragments) {\n /* eslint-disable flowtype-errors/uncovered */\n const errors = validate(schemaForValidation, withTypeNames);\n /* eslint-disable flowtype-errors/uncovered */\n if (errors.length) {\n errors.forEach((error) => {\n console.error(\n `Schema validation found errors for ${raw.loc.path}!`,\n );\n console.error(printed);\n console.error(error);\n validationFailures++;\n });\n }\n /* eslint-enable flowtype-errors/uncovered */\n }\n\n try {\n generateTypeFiles(\n raw.loc.path,\n schemaForTypeGeneration,\n withTypeNames,\n processedOptions,\n );\n // eslint-disable-next-line flowtype-errors/uncovered\n } catch (err) {\n console.error(`Error while generating operation from ${raw.loc.path}`);\n console.error(printed);\n // eslint-disable-next-line flowtype-errors/uncovered\n console.error(err);\n validationFailures++;\n }\n});\n\nif (validationFailures) {\n console.error(\n `Encountered ${validationFailures} validation failures while printing types.`,\n );\n // eslint-disable-next-line flowtype-errors/uncovered\n process.exit(1);\n}\n\nif (config.dumpOperations) {\n const dumpOperations = config.dumpOperations;\n const parent = dirname(dumpOperations);\n mkdirSync(parent, {recursive: true});\n writeFileSync(\n dumpOperations,\n JSON.stringify(printedOperations.sort(), null, 2),\n );\n}\n"],"file":"run.js"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.longestMatchingPath = void 0;
7
+
8
+ var _path = _interopRequireDefault(require("path"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ const longestMatchingPath = (filePath, subConfigPaths) => {
13
+ const {
14
+ dir
15
+ } = _path.default.parse(filePath);
16
+
17
+ return subConfigPaths.reduce((closest, key) => dir.includes(key) && closest.length < key.length ? key : closest, '');
18
+ };
19
+
20
+ exports.longestMatchingPath = longestMatchingPath;
21
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1,14 @@
1
+ // @flow
2
+ import path from 'path';
3
+
4
+ export const longestMatchingPath = (
5
+ filePath: string,
6
+ subConfigPaths: string[],
7
+ ): string => {
8
+ const {dir} = path.parse(filePath);
9
+ return subConfigPaths.reduce(
10
+ (closest: string, key: string) =>
11
+ dir.includes(key) && closest.length < key.length ? key : closest,
12
+ '',
13
+ );
14
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/utils.js"],"names":["longestMatchingPath","filePath","subConfigPaths","dir","path","parse","reduce","closest","key","includes","length"],"mappings":";;;;;;;AACA;;;;AAEO,MAAMA,mBAAmB,GAAG,CAC/BC,QAD+B,EAE/BC,cAF+B,KAGtB;AACT,QAAM;AAACC,IAAAA;AAAD,MAAQC,cAAKC,KAAL,CAAWJ,QAAX,CAAd;;AACA,SAAOC,cAAc,CAACI,MAAf,CACH,CAACC,OAAD,EAAkBC,GAAlB,KACIL,GAAG,CAACM,QAAJ,CAAaD,GAAb,KAAqBD,OAAO,CAACG,MAAR,GAAiBF,GAAG,CAACE,MAA1C,GAAmDF,GAAnD,GAAyDD,OAF1D,EAGH,EAHG,CAAP;AAKH,CAVM","sourcesContent":["// @flow\nimport path from 'path';\n\nexport const longestMatchingPath = (\n filePath: string,\n subConfigPaths: string[],\n): string => {\n const {dir} = path.parse(filePath);\n return subConfigPaths.reduce(\n (closest: string, key: string) =>\n dir.includes(key) && closest.length < key.length ? key : closest,\n '',\n );\n};\n"],"file":"utils.js"}
package/dist/enums.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.scalarTypeToFlow = exports.enumTypeToFlow = exports.builtinScalars = void 0;
6
+ exports.scalarTypeToFlow = exports.experimentalEnumTypeToFlow = exports.enumTypeToFlow = exports.builtinScalars = void 0;
7
7
 
8
8
  var babelTypes = _interopRequireWildcard(require("@babel/types"));
9
9
 
@@ -16,6 +16,19 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
16
16
  /**
17
17
  * Both input & output types can have enums & scalars.
18
18
  */
19
+ const experimentalEnumTypeToFlow = (config, enumConfig, description) => {
20
+ const enumDeclaration = babelTypes.enumDeclaration( // pass id into generic type annotation
21
+ babelTypes.identifier(enumConfig.name), babelTypes.enumStringBody(enumConfig.enumValues.map(v => babelTypes.enumDefaultedMember(babelTypes.identifier(v.name)))));
22
+
23
+ if (config.experimentalEnumsMap) {
24
+ config.experimentalEnumsMap[enumConfig.name] = enumDeclaration;
25
+ }
26
+
27
+ return (0, _utils.maybeAddDescriptionComment)(description, babelTypes.genericTypeAnnotation(enumDeclaration.id));
28
+ };
29
+
30
+ exports.experimentalEnumTypeToFlow = experimentalEnumTypeToFlow;
31
+
19
32
  const enumTypeToFlow = (config, name) => {
20
33
  const enumConfig = config.schema.enumsByName[name];
21
34
  let combinedDescription = enumConfig.enumValues.map(n => `- ${n.name}` + (n.description ? '\n\n ' + n.description.replace(/\n/g, '\n ') : '')).join('\n');
@@ -24,7 +37,7 @@ const enumTypeToFlow = (config, name) => {
24
37
  combinedDescription = enumConfig.description + '\n\n' + combinedDescription;
25
38
  }
26
39
 
27
- return (0, _utils.maybeAddDescriptionComment)(combinedDescription, babelTypes.unionTypeAnnotation(enumConfig.enumValues.map(n => babelTypes.stringLiteralTypeAnnotation(n.name))));
40
+ return config.experimentalEnumsMap ? experimentalEnumTypeToFlow(config, enumConfig, combinedDescription) : (0, _utils.maybeAddDescriptionComment)(combinedDescription, babelTypes.unionTypeAnnotation(enumConfig.enumValues.map(n => babelTypes.stringLiteralTypeAnnotation(n.name))));
28
41
  };
29
42
 
30
43
  exports.enumTypeToFlow = enumTypeToFlow;
@@ -3,9 +3,35 @@
3
3
  * Both input & output types can have enums & scalars.
4
4
  */
5
5
  import * as babelTypes from '@babel/types';
6
- import {type BabelNodeFlowType} from '@babel/types';
6
+ import type {BabelNodeFlowType} from '@babel/types';
7
7
  import type {Config} from './types';
8
8
  import {maybeAddDescriptionComment} from './utils';
9
+ import type {IntrospectionEnumType} from 'graphql/utilities/introspectionQuery';
10
+
11
+ export const experimentalEnumTypeToFlow = (
12
+ config: Config,
13
+ enumConfig: IntrospectionEnumType,
14
+ description: string,
15
+ ): BabelNodeFlowType => {
16
+ const enumDeclaration = babelTypes.enumDeclaration(
17
+ // pass id into generic type annotation
18
+ babelTypes.identifier(enumConfig.name),
19
+ babelTypes.enumStringBody(
20
+ enumConfig.enumValues.map((v) =>
21
+ babelTypes.enumDefaultedMember(babelTypes.identifier(v.name)),
22
+ ),
23
+ ),
24
+ );
25
+
26
+ if (config.experimentalEnumsMap) {
27
+ config.experimentalEnumsMap[enumConfig.name] = enumDeclaration;
28
+ }
29
+
30
+ return maybeAddDescriptionComment(
31
+ description,
32
+ babelTypes.genericTypeAnnotation(enumDeclaration.id),
33
+ );
34
+ };
9
35
 
10
36
  export const enumTypeToFlow = (
11
37
  config: Config,
@@ -25,14 +51,17 @@ export const enumTypeToFlow = (
25
51
  combinedDescription =
26
52
  enumConfig.description + '\n\n' + combinedDescription;
27
53
  }
28
- return maybeAddDescriptionComment(
29
- combinedDescription,
30
- babelTypes.unionTypeAnnotation(
31
- enumConfig.enumValues.map((n) =>
32
- babelTypes.stringLiteralTypeAnnotation(n.name),
33
- ),
34
- ),
35
- );
54
+
55
+ return config.experimentalEnumsMap
56
+ ? experimentalEnumTypeToFlow(config, enumConfig, combinedDescription)
57
+ : maybeAddDescriptionComment(
58
+ combinedDescription,
59
+ babelTypes.unionTypeAnnotation(
60
+ enumConfig.enumValues.map((n) =>
61
+ babelTypes.stringLiteralTypeAnnotation(n.name),
62
+ ),
63
+ ),
64
+ );
36
65
  };
37
66
 
38
67
  export const builtinScalars: {[key: string]: string} = {
package/dist/enums.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/enums.js"],"names":["enumTypeToFlow","config","name","enumConfig","schema","enumsByName","combinedDescription","enumValues","map","n","description","replace","join","babelTypes","unionTypeAnnotation","stringLiteralTypeAnnotation","builtinScalars","Boolean","String","DateTime","Date","ID","Int","Float","scalarTypeToFlow","genericTypeAnnotation","identifier","underlyingType","scalars","errors","push"],"mappings":";;;;;;;AAIA;;AAGA;;;;;;AANA;AACA;AACA;AAMO,MAAMA,cAAc,GAAG,CAC1BC,MAD0B,EAE1BC,IAF0B,KAGN;AACpB,QAAMC,UAAU,GAAGF,MAAM,CAACG,MAAP,CAAcC,WAAd,CAA0BH,IAA1B,CAAnB;AACA,MAAII,mBAAmB,GAAGH,UAAU,CAACI,UAAX,CACrBC,GADqB,CAEjBC,CAAD,IACK,KAAIA,CAAC,CAACP,IAAK,EAAZ,IACCO,CAAC,CAACC,WAAF,GACK,eAAeD,CAAC,CAACC,WAAF,CAAcC,OAAd,CAAsB,KAAtB,EAA6B,UAA7B,CADpB,GAEK,EAHN,CAHc,EAQrBC,IARqB,CAQhB,IARgB,CAA1B;;AASA,MAAIT,UAAU,CAACO,WAAf,EAA4B;AACxBJ,IAAAA,mBAAmB,GACfH,UAAU,CAACO,WAAX,GAAyB,MAAzB,GAAkCJ,mBADtC;AAEH;;AACD,SAAO,uCACHA,mBADG,EAEHO,UAAU,CAACC,mBAAX,CACIX,UAAU,CAACI,UAAX,CAAsBC,GAAtB,CAA2BC,CAAD,IACtBI,UAAU,CAACE,2BAAX,CAAuCN,CAAC,CAACP,IAAzC,CADJ,CADJ,CAFG,CAAP;AAQH,CA1BM;;;AA4BA,MAAMc,cAAuC,GAAG;AACnDC,EAAAA,OAAO,EAAE,SAD0C;AAEnDC,EAAAA,MAAM,EAAE,QAF2C;AAGnDC,EAAAA,QAAQ,EAAE,QAHyC;AAInDC,EAAAA,IAAI,EAAE,QAJ6C;AAKnDC,EAAAA,EAAE,EAAE,QAL+C;AAMnDC,EAAAA,GAAG,EAAE,QAN8C;AAOnDC,EAAAA,KAAK,EAAE;AAP4C,CAAhD;;;AAUA,MAAMC,gBAAgB,GAAG,CAC5BvB,MAD4B,EAE5BC,IAF4B,KAGR;AACpB,MAAIc,cAAc,CAACd,IAAD,CAAlB,EAA0B;AACtB,WAAOW,UAAU,CAACY,qBAAX,CACHZ,UAAU,CAACa,UAAX,CAAsBV,cAAc,CAACd,IAAD,CAApC,CADG,CAAP;AAGH;;AACD,QAAMyB,cAAc,GAAG1B,MAAM,CAAC2B,OAAP,CAAe1B,IAAf,CAAvB;;AACA,MAAIyB,cAAc,IAAI,IAAtB,EAA4B;AACxB,WAAOd,UAAU,CAACY,qBAAX,CACHZ,UAAU,CAACa,UAAX,CAAsBC,cAAtB,CADG,CAAP;AAGH;;AACD1B,EAAAA,MAAM,CAAC4B,MAAP,CAAcC,IAAd,CACK,sBAAqB5B,IAAK,sFAD/B;AAGA,SAAOW,UAAU,CAACY,qBAAX,CACHZ,UAAU,CAACa,UAAX,CAAuB,mBAAkBxB,IAAK,IAA9C,CADG,CAAP;AAGH,CArBM","sourcesContent":["// @flow\n/**\n * Both input & output types can have enums & scalars.\n */\nimport * as babelTypes from '@babel/types';\nimport {type BabelNodeFlowType} from '@babel/types';\nimport type {Config} from './types';\nimport {maybeAddDescriptionComment} from './utils';\n\nexport const enumTypeToFlow = (\n config: Config,\n name: string,\n): BabelNodeFlowType => {\n const enumConfig = config.schema.enumsByName[name];\n let combinedDescription = enumConfig.enumValues\n .map(\n (n) =>\n `- ${n.name}` +\n (n.description\n ? '\\n\\n ' + n.description.replace(/\\n/g, '\\n ')\n : ''),\n )\n .join('\\n');\n if (enumConfig.description) {\n combinedDescription =\n enumConfig.description + '\\n\\n' + combinedDescription;\n }\n return maybeAddDescriptionComment(\n combinedDescription,\n babelTypes.unionTypeAnnotation(\n enumConfig.enumValues.map((n) =>\n babelTypes.stringLiteralTypeAnnotation(n.name),\n ),\n ),\n );\n};\n\nexport const builtinScalars: {[key: string]: string} = {\n Boolean: 'boolean',\n String: 'string',\n DateTime: 'string',\n Date: 'string',\n ID: 'string',\n Int: 'number',\n Float: 'number',\n};\n\nexport const scalarTypeToFlow = (\n config: Config,\n name: string,\n): BabelNodeFlowType => {\n if (builtinScalars[name]) {\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier(builtinScalars[name]),\n );\n }\n const underlyingType = config.scalars[name];\n if (underlyingType != null) {\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier(underlyingType),\n );\n }\n config.errors.push(\n `Unexpected scalar '${name}'! Please add it to the \"scalars\" argument at the callsite of 'generateFlowTypes()'.`,\n );\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier(`UNKNOWN_SCALAR[\"${name}\"]`),\n );\n};\n"],"file":"enums.js"}
1
+ {"version":3,"sources":["../src/enums.js"],"names":["experimentalEnumTypeToFlow","config","enumConfig","description","enumDeclaration","babelTypes","identifier","name","enumStringBody","enumValues","map","v","enumDefaultedMember","experimentalEnumsMap","genericTypeAnnotation","id","enumTypeToFlow","schema","enumsByName","combinedDescription","n","replace","join","unionTypeAnnotation","stringLiteralTypeAnnotation","builtinScalars","Boolean","String","DateTime","Date","ID","Int","Float","scalarTypeToFlow","underlyingType","scalars","errors","push"],"mappings":";;;;;;;AAIA;;AAGA;;;;;;AANA;AACA;AACA;AAOO,MAAMA,0BAA0B,GAAG,CACtCC,MADsC,EAEtCC,UAFsC,EAGtCC,WAHsC,KAIlB;AACpB,QAAMC,eAAe,GAAGC,UAAU,CAACD,eAAX,EACpB;AACAC,EAAAA,UAAU,CAACC,UAAX,CAAsBJ,UAAU,CAACK,IAAjC,CAFoB,EAGpBF,UAAU,CAACG,cAAX,CACIN,UAAU,CAACO,UAAX,CAAsBC,GAAtB,CAA2BC,CAAD,IACtBN,UAAU,CAACO,mBAAX,CAA+BP,UAAU,CAACC,UAAX,CAAsBK,CAAC,CAACJ,IAAxB,CAA/B,CADJ,CADJ,CAHoB,CAAxB;;AAUA,MAAIN,MAAM,CAACY,oBAAX,EAAiC;AAC7BZ,IAAAA,MAAM,CAACY,oBAAP,CAA4BX,UAAU,CAACK,IAAvC,IAA+CH,eAA/C;AACH;;AAED,SAAO,uCACHD,WADG,EAEHE,UAAU,CAACS,qBAAX,CAAiCV,eAAe,CAACW,EAAjD,CAFG,CAAP;AAIH,CAvBM;;;;AAyBA,MAAMC,cAAc,GAAG,CAC1Bf,MAD0B,EAE1BM,IAF0B,KAGN;AACpB,QAAML,UAAU,GAAGD,MAAM,CAACgB,MAAP,CAAcC,WAAd,CAA0BX,IAA1B,CAAnB;AACA,MAAIY,mBAAmB,GAAGjB,UAAU,CAACO,UAAX,CACrBC,GADqB,CAEjBU,CAAD,IACK,KAAIA,CAAC,CAACb,IAAK,EAAZ,IACCa,CAAC,CAACjB,WAAF,GACK,eAAeiB,CAAC,CAACjB,WAAF,CAAckB,OAAd,CAAsB,KAAtB,EAA6B,UAA7B,CADpB,GAEK,EAHN,CAHc,EAQrBC,IARqB,CAQhB,IARgB,CAA1B;;AASA,MAAIpB,UAAU,CAACC,WAAf,EAA4B;AACxBgB,IAAAA,mBAAmB,GACfjB,UAAU,CAACC,WAAX,GAAyB,MAAzB,GAAkCgB,mBADtC;AAEH;;AAED,SAAOlB,MAAM,CAACY,oBAAP,GACDb,0BAA0B,CAACC,MAAD,EAASC,UAAT,EAAqBiB,mBAArB,CADzB,GAED,uCACIA,mBADJ,EAEId,UAAU,CAACkB,mBAAX,CACIrB,UAAU,CAACO,UAAX,CAAsBC,GAAtB,CAA2BU,CAAD,IACtBf,UAAU,CAACmB,2BAAX,CAAuCJ,CAAC,CAACb,IAAzC,CADJ,CADJ,CAFJ,CAFN;AAUH,CA7BM;;;AA+BA,MAAMkB,cAAuC,GAAG;AACnDC,EAAAA,OAAO,EAAE,SAD0C;AAEnDC,EAAAA,MAAM,EAAE,QAF2C;AAGnDC,EAAAA,QAAQ,EAAE,QAHyC;AAInDC,EAAAA,IAAI,EAAE,QAJ6C;AAKnDC,EAAAA,EAAE,EAAE,QAL+C;AAMnDC,EAAAA,GAAG,EAAE,QAN8C;AAOnDC,EAAAA,KAAK,EAAE;AAP4C,CAAhD;;;AAUA,MAAMC,gBAAgB,GAAG,CAC5BhC,MAD4B,EAE5BM,IAF4B,KAGR;AACpB,MAAIkB,cAAc,CAAClB,IAAD,CAAlB,EAA0B;AACtB,WAAOF,UAAU,CAACS,qBAAX,CACHT,UAAU,CAACC,UAAX,CAAsBmB,cAAc,CAAClB,IAAD,CAApC,CADG,CAAP;AAGH;;AACD,QAAM2B,cAAc,GAAGjC,MAAM,CAACkC,OAAP,CAAe5B,IAAf,CAAvB;;AACA,MAAI2B,cAAc,IAAI,IAAtB,EAA4B;AACxB,WAAO7B,UAAU,CAACS,qBAAX,CACHT,UAAU,CAACC,UAAX,CAAsB4B,cAAtB,CADG,CAAP;AAGH;;AACDjC,EAAAA,MAAM,CAACmC,MAAP,CAAcC,IAAd,CACK,sBAAqB9B,IAAK,sFAD/B;AAGA,SAAOF,UAAU,CAACS,qBAAX,CACHT,UAAU,CAACC,UAAX,CAAuB,mBAAkBC,IAAK,IAA9C,CADG,CAAP;AAGH,CArBM","sourcesContent":["// @flow\n/**\n * Both input & output types can have enums & scalars.\n */\nimport * as babelTypes from '@babel/types';\nimport type {BabelNodeFlowType} from '@babel/types';\nimport type {Config} from './types';\nimport {maybeAddDescriptionComment} from './utils';\nimport type {IntrospectionEnumType} from 'graphql/utilities/introspectionQuery';\n\nexport const experimentalEnumTypeToFlow = (\n config: Config,\n enumConfig: IntrospectionEnumType,\n description: string,\n): BabelNodeFlowType => {\n const enumDeclaration = babelTypes.enumDeclaration(\n // pass id into generic type annotation\n babelTypes.identifier(enumConfig.name),\n babelTypes.enumStringBody(\n enumConfig.enumValues.map((v) =>\n babelTypes.enumDefaultedMember(babelTypes.identifier(v.name)),\n ),\n ),\n );\n\n if (config.experimentalEnumsMap) {\n config.experimentalEnumsMap[enumConfig.name] = enumDeclaration;\n }\n\n return maybeAddDescriptionComment(\n description,\n babelTypes.genericTypeAnnotation(enumDeclaration.id),\n );\n};\n\nexport const enumTypeToFlow = (\n config: Config,\n name: string,\n): BabelNodeFlowType => {\n const enumConfig = config.schema.enumsByName[name];\n let combinedDescription = enumConfig.enumValues\n .map(\n (n) =>\n `- ${n.name}` +\n (n.description\n ? '\\n\\n ' + n.description.replace(/\\n/g, '\\n ')\n : ''),\n )\n .join('\\n');\n if (enumConfig.description) {\n combinedDescription =\n enumConfig.description + '\\n\\n' + combinedDescription;\n }\n\n return config.experimentalEnumsMap\n ? experimentalEnumTypeToFlow(config, enumConfig, combinedDescription)\n : maybeAddDescriptionComment(\n combinedDescription,\n babelTypes.unionTypeAnnotation(\n enumConfig.enumValues.map((n) =>\n babelTypes.stringLiteralTypeAnnotation(n.name),\n ),\n ),\n );\n};\n\nexport const builtinScalars: {[key: string]: string} = {\n Boolean: 'boolean',\n String: 'string',\n DateTime: 'string',\n Date: 'string',\n ID: 'string',\n Int: 'number',\n Float: 'number',\n};\n\nexport const scalarTypeToFlow = (\n config: Config,\n name: string,\n): BabelNodeFlowType => {\n if (builtinScalars[name]) {\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier(builtinScalars[name]),\n );\n }\n const underlyingType = config.scalars[name];\n if (underlyingType != null) {\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier(underlyingType),\n );\n }\n config.errors.push(\n `Unexpected scalar '${name}'! Please add it to the \"scalars\" argument at the callsite of 'generateFlowTypes()'.`,\n );\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier(`UNKNOWN_SCALAR[\"${name}\"]`),\n );\n};\n"],"file":"enums.js"}
@@ -52,7 +52,8 @@ const generateTypeFileContents = (fileName, schema, document, options, generated
52
52
  typeName,
53
53
  code,
54
54
  isFragment,
55
- extraTypes
55
+ extraTypes,
56
+ experimentalEnums
56
57
  }) => {
57
58
  // We write all generated files to a `__generated__` subdir to keep
58
59
  // things tidy.
@@ -66,9 +67,17 @@ const generateTypeFileContents = (fileName, schema, document, options, generated
66
67
  fileContents += `\nexport type ${name} = ${typeName}['response'];\n` + `export type ${name}Variables = ${typeName}['variables'];\n`;
67
68
  }
68
69
 
69
- Object.keys(extraTypes).forEach(name => {
70
- fileContents += `\n\nexport type ${name} = ${extraTypes[name]};`;
71
- });
70
+ Object.keys(extraTypes).forEach(name => fileContents += `\n\nexport type ${name} = ${extraTypes[name]};`);
71
+ const enumNames = Object.keys(experimentalEnums);
72
+
73
+ if (options.experimentalEnums && enumNames.length) {
74
+ // TODO(somewhatabstract, FEI-4172): Update to fixed eslint-plugin-flowtype
75
+ // and remove this disable.
76
+ fileContents += `\n\n/* eslint-disable no-undef */`;
77
+ enumNames.forEach(name => fileContents += `\nexport ${experimentalEnums[name]};\n`);
78
+ fileContents += `/* eslint-enable no-undef */`;
79
+ }
80
+
72
81
  addToIndex(targetPath, typeName);
73
82
  files[targetPath] = fileContents // Remove whitespace from the ends of lines; babel's generate sometimes
74
83
  // leaves them hanging around.
@@ -82,10 +91,23 @@ const generateTypeFileContents = (fileName, schema, document, options, generated
82
91
 
83
92
  exports.generateTypeFileContents = generateTypeFileContents;
84
93
 
85
- const generateTypeFiles = (fileName, schema, document, options) => {
94
+ const getGeneratedDir = (fileName, options) => {
86
95
  var _options$generatedDir;
87
96
 
88
- const generatedDir = _path.default.join(_path.default.dirname(fileName), (_options$generatedDir = options.generatedDirectory) !== null && _options$generatedDir !== void 0 ? _options$generatedDir : '__generated__');
97
+ const generatedDirectory = (_options$generatedDir = options.generatedDirectory) !== null && _options$generatedDir !== void 0 ? _options$generatedDir : '__generated__';
98
+
99
+ if (_path.default.isAbsolute(generatedDirectory)) {
100
+ // fileName is absolute here, so we make it relative to cwd
101
+ // for more reasonable filenames. We convert leading ..'s
102
+ // to `__` so this doesn't escape the output directory.
103
+ return _path.default.join(generatedDirectory, _path.default.relative(process.cwd(), _path.default.dirname(fileName)).replace(/\.\.\//g, '__/'));
104
+ } else {
105
+ return _path.default.join(_path.default.dirname(fileName), generatedDirectory);
106
+ }
107
+ };
108
+
109
+ const generateTypeFiles = (fileName, schema, document, options) => {
110
+ const generatedDir = getGeneratedDir(fileName, options);
89
111
 
90
112
  const indexFile = _path.default.join(generatedDir, 'index.js');
91
113
 
@@ -133,7 +155,8 @@ const processPragmas = (options, rawSource) => {
133
155
  splitTypes: options.splitTypes,
134
156
  generatedDirectory: options.generatedDirectory,
135
157
  exportAllObjectTypes: options.exportAllObjectTypes,
136
- typeFileName: options.typeFileName
158
+ typeFileName: options.typeFileName,
159
+ experimentalEnums: options.experimentalEnums
137
160
  };
138
161
  } else {
139
162
  return null;
@@ -21,6 +21,7 @@ export type ExternalOptions = {
21
21
  generatedDirectory?: string,
22
22
  exportAllObjectTypes?: boolean,
23
23
  typeFileName?: string,
24
+ experimentalEnums?: boolean,
24
25
  };
25
26
 
26
27
  export const indexPrelude = (regenerateCommand?: string): string => `// @flow
@@ -62,54 +63,82 @@ export const generateTypeFileContents = (
62
63
  };
63
64
 
64
65
  const generated = documentToFlowTypes(document, schema, options);
65
- generated.forEach(({name, typeName, code, isFragment, extraTypes}) => {
66
- // We write all generated files to a `__generated__` subdir to keep
67
- // things tidy.
68
- const targetFileName = options.typeFileName
69
- ? options.typeFileName.replace('[operationName]', name)
70
- : `${name}.js`;
71
- const targetPath = path.join(generatedDir, targetFileName);
72
-
73
- let fileContents =
74
- '// @' +
75
- `flow\n// AUTOGENERATED -- DO NOT EDIT\n` +
76
- `// Generated for operation '${name}' in file '../${path.basename(
77
- fileName,
78
- )}'\n` +
79
- (options.regenerateCommand
80
- ? `// To regenerate, run '${options.regenerateCommand}'.\n`
81
- : '') +
82
- code;
83
- if (options.splitTypes && !isFragment) {
84
- fileContents +=
85
- `\nexport type ${name} = ${typeName}['response'];\n` +
86
- `export type ${name}Variables = ${typeName}['variables'];\n`;
87
- }
88
- Object.keys(extraTypes).forEach((name) => {
89
- fileContents += `\n\nexport type ${name} = ${extraTypes[name]};`;
90
- });
91
-
92
- addToIndex(targetPath, typeName);
93
- files[targetPath] =
94
- fileContents
95
- // Remove whitespace from the ends of lines; babel's generate sometimes
96
- // leaves them hanging around.
97
- .replace(/\s+$/gm, '') + '\n';
98
- });
66
+ generated.forEach(
67
+ ({name, typeName, code, isFragment, extraTypes, experimentalEnums}) => {
68
+ // We write all generated files to a `__generated__` subdir to keep
69
+ // things tidy.
70
+ const targetFileName = options.typeFileName
71
+ ? options.typeFileName.replace('[operationName]', name)
72
+ : `${name}.js`;
73
+ const targetPath = path.join(generatedDir, targetFileName);
74
+
75
+ let fileContents =
76
+ '// @' +
77
+ `flow\n// AUTOGENERATED -- DO NOT EDIT\n` +
78
+ `// Generated for operation '${name}' in file '../${path.basename(
79
+ fileName,
80
+ )}'\n` +
81
+ (options.regenerateCommand
82
+ ? `// To regenerate, run '${options.regenerateCommand}'.\n`
83
+ : '') +
84
+ code;
85
+ if (options.splitTypes && !isFragment) {
86
+ fileContents +=
87
+ `\nexport type ${name} = ${typeName}['response'];\n` +
88
+ `export type ${name}Variables = ${typeName}['variables'];\n`;
89
+ }
90
+ Object.keys(extraTypes).forEach(
91
+ (name) =>
92
+ (fileContents += `\n\nexport type ${name} = ${extraTypes[name]};`),
93
+ );
94
+ const enumNames = Object.keys(experimentalEnums);
95
+ if (options.experimentalEnums && enumNames.length) {
96
+ // TODO(somewhatabstract, FEI-4172): Update to fixed eslint-plugin-flowtype
97
+ // and remove this disable.
98
+ fileContents += `\n\n/* eslint-disable no-undef */`;
99
+ enumNames.forEach(
100
+ (name) =>
101
+ (fileContents += `\nexport ${experimentalEnums[name]};\n`),
102
+ );
103
+ fileContents += `/* eslint-enable no-undef */`;
104
+ }
105
+
106
+ addToIndex(targetPath, typeName);
107
+ files[targetPath] =
108
+ fileContents
109
+ // Remove whitespace from the ends of lines; babel's generate sometimes
110
+ // leaves them hanging around.
111
+ .replace(/\s+$/gm, '') + '\n';
112
+ },
113
+ );
99
114
 
100
115
  return {files, indexContents};
101
116
  };
102
117
 
118
+ const getGeneratedDir = (fileName: string, options: Options) => {
119
+ const generatedDirectory = options.generatedDirectory ?? '__generated__';
120
+ if (path.isAbsolute(generatedDirectory)) {
121
+ // fileName is absolute here, so we make it relative to cwd
122
+ // for more reasonable filenames. We convert leading ..'s
123
+ // to `__` so this doesn't escape the output directory.
124
+ return path.join(
125
+ generatedDirectory,
126
+ path
127
+ .relative(process.cwd(), path.dirname(fileName))
128
+ .replace(/\.\.\//g, '__/'),
129
+ );
130
+ } else {
131
+ return path.join(path.dirname(fileName), generatedDirectory);
132
+ }
133
+ };
134
+
103
135
  export const generateTypeFiles = (
104
136
  fileName: string,
105
137
  schema: Schema,
106
138
  document: DocumentNode,
107
139
  options: Options,
108
140
  ) => {
109
- const generatedDir = path.join(
110
- path.dirname(fileName),
111
- options.generatedDirectory ?? '__generated__',
112
- );
141
+ const generatedDir = getGeneratedDir(fileName, options);
113
142
  const indexFile = path.join(generatedDir, 'index.js');
114
143
 
115
144
  if (!fs.existsSync(generatedDir)) {
@@ -164,6 +193,7 @@ export const processPragmas = (
164
193
  generatedDirectory: options.generatedDirectory,
165
194
  exportAllObjectTypes: options.exportAllObjectTypes,
166
195
  typeFileName: options.typeFileName,
196
+ experimentalEnums: options.experimentalEnums,
167
197
  };
168
198
  } else {
169
199
  return null;