@khanacademy/graphql-flow 0.2.3 → 0.2.4

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,11 @@
1
1
  # @khanacademy/graphql-flow
2
2
 
3
+ ## 0.2.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 843839c: Add 'dumpOperations' config option, to enable safelisting
8
+
3
9
  ## 0.2.3
4
10
 
5
11
  ### Patch Changes
@@ -20,7 +20,7 @@ const loadConfigFile = configFile => {
20
20
 
21
21
  // eslint-disable-next-line flowtype-errors/uncovered
22
22
  const data = JSON.parse(_fs.default.readFileSync(configFile, 'utf8'));
23
- const toplevelKeys = ['excludes', 'schemaFilePath', 'options'];
23
+ const toplevelKeys = ['excludes', 'schemaFilePath', 'options', 'dumpOperations'];
24
24
  Object.keys(data).forEach(k => {
25
25
  if (!toplevelKeys.includes(k)) {
26
26
  throw new Error(`Invalid attribute in config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(', ')}`);
@@ -39,7 +39,8 @@ const loadConfigFile = configFile => {
39
39
  return {
40
40
  options: (_data$options = data.options) !== null && _data$options !== void 0 ? _data$options : {},
41
41
  excludes: (_data$excludes$map = (_data$excludes = data.excludes) === null || _data$excludes === void 0 ? void 0 : _data$excludes.map(string => new RegExp(string))) !== null && _data$excludes$map !== void 0 ? _data$excludes$map : [],
42
- schemaFilePath: _path.default.join(_path.default.dirname(configFile), data.schemaFilePath)
42
+ schemaFilePath: _path.default.join(_path.default.dirname(configFile), data.schemaFilePath),
43
+ dumpOperations: data.dumpOperations
43
44
  };
44
45
  };
45
46
  /**
@@ -18,6 +18,7 @@ import path from 'path';
18
18
  export type CliConfig = {
19
19
  excludes: Array<RegExp>,
20
20
  schemaFilePath: string,
21
+ dumpOperations?: string,
21
22
  options: ExternalOptions,
22
23
  };
23
24
 
@@ -29,12 +30,18 @@ type JSONConfig = {
29
30
  excludes?: Array<string>,
30
31
  schemaFilePath: string,
31
32
  options?: ExternalOptions,
33
+ dumpOperations?: string,
32
34
  };
33
35
 
34
36
  export const loadConfigFile = (configFile: string): CliConfig => {
35
37
  // eslint-disable-next-line flowtype-errors/uncovered
36
38
  const data: JSONConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));
37
- const toplevelKeys = ['excludes', 'schemaFilePath', 'options'];
39
+ const toplevelKeys = [
40
+ 'excludes',
41
+ 'schemaFilePath',
42
+ 'options',
43
+ 'dumpOperations',
44
+ ];
38
45
  Object.keys(data).forEach((k) => {
39
46
  if (!toplevelKeys.includes(k)) {
40
47
  throw new Error(
@@ -75,6 +82,7 @@ export const loadConfigFile = (configFile: string): CliConfig => {
75
82
  path.dirname(configFile),
76
83
  data.schemaFilePath,
77
84
  ),
85
+ dumpOperations: data.dumpOperations,
78
86
  };
79
87
  };
80
88
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/config.js"],"names":["loadConfigFile","configFile","data","JSON","parse","fs","readFileSync","toplevelKeys","Object","keys","forEach","k","includes","Error","join","options","externalOptionsKeys","excludes","map","string","RegExp","schemaFilePath","path","dirname","getSchemas","raw","endsWith","schemaForValidation","queryResponse","descriptions","schemaForTypeGeneration","introspectionData"],"mappings":";;;;;;;AAKA;;AAEA;;AACA;;AAOA;;;;AAkBO,MAAMA,cAAc,GAAIC,UAAD,IAAmC;AAAA;;AAC7D;AACA,QAAMC,IAAgB,GAAGC,IAAI,CAACC,KAAL,CAAWC,YAAGC,YAAH,CAAgBL,UAAhB,EAA4B,MAA5B,CAAX,CAAzB;AACA,QAAMM,YAAY,GAAG,CAAC,UAAD,EAAa,gBAAb,EAA+B,SAA/B,CAArB;AACAC,EAAAA,MAAM,CAACC,IAAP,CAAYP,IAAZ,EAAkBQ,OAAlB,CAA2BC,CAAD,IAAO;AAC7B,QAAI,CAACJ,YAAY,CAACK,QAAb,CAAsBD,CAAtB,CAAL,EAA+B;AAC3B,YAAM,IAAIE,KAAJ,CACD,oCAAmCZ,UAAW,KAAIU,CAAE,yBAAwBJ,YAAY,CAACO,IAAb,CACzE,IADyE,CAE3E,EAHA,CAAN;AAKH;AACJ,GARD;;AASA,MAAIZ,IAAI,CAACa,OAAT,EAAkB;AACd,UAAMC,mBAAmB,GAAG,CACxB,QADwB,EAExB,aAFwB,EAGxB,cAHwB,EAIxB,SAJwB,EAKxB,mBALwB,EAMxB,mBANwB,EAOxB,eAPwB,EAQxB,YARwB,EASxB,oBATwB,EAUxB,sBAVwB,EAWxB,cAXwB,CAA5B;AAaAR,IAAAA,MAAM,CAACC,IAAP,CAAYP,IAAI,CAACa,OAAjB,EAA0BL,OAA1B,CAAmCC,CAAD,IAAO;AACrC,UAAI,CAACK,mBAAmB,CAACJ,QAApB,CAA6BD,CAA7B,CAAL,EAAsC;AAClC,cAAM,IAAIE,KAAJ,CACD,iCAAgCZ,UAAW,KAAIU,CAAE,sBAAqBK,mBAAmB,CAACF,IAApB,CACnE,IADmE,CAErE,EAHA,CAAN;AAKH;AACJ,KARD;AASH;;AACD,SAAO;AACHC,IAAAA,OAAO,mBAAEb,IAAI,CAACa,OAAP,yDAAkB,EADtB;AAEHE,IAAAA,QAAQ,0CAAEf,IAAI,CAACe,QAAP,mDAAE,eAAeC,GAAf,CAAoBC,MAAD,IAAY,IAAIC,MAAJ,CAAWD,MAAX,CAA/B,CAAF,mEAAwD,EAF7D;AAGHE,IAAAA,cAAc,EAAEC,cAAKR,IAAL,CACZQ,cAAKC,OAAL,CAAatB,UAAb,CADY,EAEZC,IAAI,CAACmB,cAFO;AAHb,GAAP;AAQH,CA7CM;AA+CP;AACA;AACA;;;;;AACO,MAAMG,UAAU,GAAIH,cAAD,IAAqD;AAC3E,QAAMI,GAAG,GAAGpB,YAAGC,YAAH,CAAgBe,cAAhB,EAAgC,MAAhC,CAAZ;;AACA,MAAIA,cAAc,CAACK,QAAf,CAAwB,UAAxB,CAAJ,EAAyC;AACrC,UAAMC,mBAAmB,GAAG,0BAAYF,GAAZ,CAA5B;AACA,UAAMG,aAAa,GAAG,0BAClBD,mBADkB,EAElB,oCAAsB;AAACE,MAAAA,YAAY,EAAE;AAAf,KAAtB,CAFkB,CAAtB;AAIA,UAAMC,uBAAuB,GAAG,+DAC5B;AACEF,IAAAA,aAAa,CAAC1B,IAFY,CAAhC;AAIA,WAAO,CAACyB,mBAAD,EAAsBG,uBAAtB,CAAP;AACH,GAXD,MAWO;AACH;AACA,UAAMC,iBAAqC,GAAG5B,IAAI,CAACC,KAAL,CAAWqB,GAAX,CAA9C;AACA,UAAME,mBAAmB,GAAG,gCAAkBI,iBAAlB,CAA5B;AACA,UAAMD,uBAAuB,GACzB,8DAA4BC,iBAA5B,CADJ;AAEA,WAAO,CAACJ,mBAAD,EAAsBG,uBAAtB,CAAP;AACH;AACJ,CArBM","sourcesContent":["// @flow\nimport type {ExternalOptions} from '../generateTypeFiles';\nimport type {Schema} from '../types';\nimport type {GraphQLSchema} from 'graphql/type/schema';\n\nimport {schemaFromIntrospectionData} from '../schemaFromIntrospectionData';\n\nimport fs from 'fs';\nimport {\n buildClientSchema,\n buildSchema,\n getIntrospectionQuery,\n graphqlSync,\n type IntrospectionQuery,\n} from 'graphql';\nimport path from 'path';\n\nexport type CliConfig = {\n excludes: Array<RegExp>,\n schemaFilePath: string,\n options: ExternalOptions,\n};\n\n/**\n * This is the json-compatible form of the config\n * object.\n */\ntype JSONConfig = {\n excludes?: Array<string>,\n schemaFilePath: string,\n options?: ExternalOptions,\n};\n\nexport const loadConfigFile = (configFile: string): CliConfig => {\n // eslint-disable-next-line flowtype-errors/uncovered\n const data: JSONConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));\n const toplevelKeys = ['excludes', 'schemaFilePath', 'options'];\n Object.keys(data).forEach((k) => {\n if (!toplevelKeys.includes(k)) {\n throw new Error(\n `Invalid attribute in config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(\n ', ',\n )}`,\n );\n }\n });\n if (data.options) {\n const externalOptionsKeys = [\n 'pragma',\n 'loosePragma',\n 'ignorePragma',\n 'scalars',\n 'strictNullability',\n 'regenerateCommand',\n 'readOnlyArray',\n 'splitTypes',\n 'generatedDirectory',\n 'exportAllObjectTypes',\n 'typeFileName',\n ];\n Object.keys(data.options).forEach((k) => {\n if (!externalOptionsKeys.includes(k)) {\n throw new Error(\n `Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(\n ', ',\n )}`,\n );\n }\n });\n }\n return {\n options: data.options ?? {},\n excludes: data.excludes?.map((string) => new RegExp(string)) ?? [],\n schemaFilePath: path.join(\n path.dirname(configFile),\n data.schemaFilePath,\n ),\n };\n};\n\n/**\n * Loads a .json 'introspection query response', or a .graphql schema definition.\n */\nexport const getSchemas = (schemaFilePath: string): [GraphQLSchema, Schema] => {\n const raw = fs.readFileSync(schemaFilePath, 'utf8');\n if (schemaFilePath.endsWith('.graphql')) {\n const schemaForValidation = buildSchema(raw);\n const queryResponse = graphqlSync(\n schemaForValidation,\n getIntrospectionQuery({descriptions: true}),\n );\n const schemaForTypeGeneration = schemaFromIntrospectionData(\n // eslint-disable-next-line flowtype-errors/uncovered\n ((queryResponse.data: any): IntrospectionQuery),\n );\n return [schemaForValidation, schemaForTypeGeneration];\n } else {\n // eslint-disable-next-line flowtype-errors/uncovered\n const introspectionData: IntrospectionQuery = JSON.parse(raw);\n const schemaForValidation = buildClientSchema(introspectionData);\n const schemaForTypeGeneration =\n schemaFromIntrospectionData(introspectionData);\n return [schemaForValidation, schemaForTypeGeneration];\n }\n};\n"],"file":"config.js"}
1
+ {"version":3,"sources":["../../src/cli/config.js"],"names":["loadConfigFile","configFile","data","JSON","parse","fs","readFileSync","toplevelKeys","Object","keys","forEach","k","includes","Error","join","options","externalOptionsKeys","excludes","map","string","RegExp","schemaFilePath","path","dirname","dumpOperations","getSchemas","raw","endsWith","schemaForValidation","queryResponse","descriptions","schemaForTypeGeneration","introspectionData"],"mappings":";;;;;;;AAKA;;AAEA;;AACA;;AAOA;;;;AAoBO,MAAMA,cAAc,GAAIC,UAAD,IAAmC;AAAA;;AAC7D;AACA,QAAMC,IAAgB,GAAGC,IAAI,CAACC,KAAL,CAAWC,YAAGC,YAAH,CAAgBL,UAAhB,EAA4B,MAA5B,CAAX,CAAzB;AACA,QAAMM,YAAY,GAAG,CACjB,UADiB,EAEjB,gBAFiB,EAGjB,SAHiB,EAIjB,gBAJiB,CAArB;AAMAC,EAAAA,MAAM,CAACC,IAAP,CAAYP,IAAZ,EAAkBQ,OAAlB,CAA2BC,CAAD,IAAO;AAC7B,QAAI,CAACJ,YAAY,CAACK,QAAb,CAAsBD,CAAtB,CAAL,EAA+B;AAC3B,YAAM,IAAIE,KAAJ,CACD,oCAAmCZ,UAAW,KAAIU,CAAE,yBAAwBJ,YAAY,CAACO,IAAb,CACzE,IADyE,CAE3E,EAHA,CAAN;AAKH;AACJ,GARD;;AASA,MAAIZ,IAAI,CAACa,OAAT,EAAkB;AACd,UAAMC,mBAAmB,GAAG,CACxB,QADwB,EAExB,aAFwB,EAGxB,cAHwB,EAIxB,SAJwB,EAKxB,mBALwB,EAMxB,mBANwB,EAOxB,eAPwB,EAQxB,YARwB,EASxB,oBATwB,EAUxB,sBAVwB,EAWxB,cAXwB,CAA5B;AAaAR,IAAAA,MAAM,CAACC,IAAP,CAAYP,IAAI,CAACa,OAAjB,EAA0BL,OAA1B,CAAmCC,CAAD,IAAO;AACrC,UAAI,CAACK,mBAAmB,CAACJ,QAApB,CAA6BD,CAA7B,CAAL,EAAsC;AAClC,cAAM,IAAIE,KAAJ,CACD,iCAAgCZ,UAAW,KAAIU,CAAE,sBAAqBK,mBAAmB,CAACF,IAApB,CACnE,IADmE,CAErE,EAHA,CAAN;AAKH;AACJ,KARD;AASH;;AACD,SAAO;AACHC,IAAAA,OAAO,mBAAEb,IAAI,CAACa,OAAP,yDAAkB,EADtB;AAEHE,IAAAA,QAAQ,0CAAEf,IAAI,CAACe,QAAP,mDAAE,eAAeC,GAAf,CAAoBC,MAAD,IAAY,IAAIC,MAAJ,CAAWD,MAAX,CAA/B,CAAF,mEAAwD,EAF7D;AAGHE,IAAAA,cAAc,EAAEC,cAAKR,IAAL,CACZQ,cAAKC,OAAL,CAAatB,UAAb,CADY,EAEZC,IAAI,CAACmB,cAFO,CAHb;AAOHG,IAAAA,cAAc,EAAEtB,IAAI,CAACsB;AAPlB,GAAP;AASH,CAnDM;AAqDP;AACA;AACA;;;;;AACO,MAAMC,UAAU,GAAIJ,cAAD,IAAqD;AAC3E,QAAMK,GAAG,GAAGrB,YAAGC,YAAH,CAAgBe,cAAhB,EAAgC,MAAhC,CAAZ;;AACA,MAAIA,cAAc,CAACM,QAAf,CAAwB,UAAxB,CAAJ,EAAyC;AACrC,UAAMC,mBAAmB,GAAG,0BAAYF,GAAZ,CAA5B;AACA,UAAMG,aAAa,GAAG,0BAClBD,mBADkB,EAElB,oCAAsB;AAACE,MAAAA,YAAY,EAAE;AAAf,KAAtB,CAFkB,CAAtB;AAIA,UAAMC,uBAAuB,GAAG,+DAC5B;AACEF,IAAAA,aAAa,CAAC3B,IAFY,CAAhC;AAIA,WAAO,CAAC0B,mBAAD,EAAsBG,uBAAtB,CAAP;AACH,GAXD,MAWO;AACH;AACA,UAAMC,iBAAqC,GAAG7B,IAAI,CAACC,KAAL,CAAWsB,GAAX,CAA9C;AACA,UAAME,mBAAmB,GAAG,gCAAkBI,iBAAlB,CAA5B;AACA,UAAMD,uBAAuB,GACzB,8DAA4BC,iBAA5B,CADJ;AAEA,WAAO,CAACJ,mBAAD,EAAsBG,uBAAtB,CAAP;AACH;AACJ,CArBM","sourcesContent":["// @flow\nimport type {ExternalOptions} from '../generateTypeFiles';\nimport type {Schema} from '../types';\nimport type {GraphQLSchema} from 'graphql/type/schema';\n\nimport {schemaFromIntrospectionData} from '../schemaFromIntrospectionData';\n\nimport fs from 'fs';\nimport {\n buildClientSchema,\n buildSchema,\n getIntrospectionQuery,\n graphqlSync,\n type IntrospectionQuery,\n} from 'graphql';\nimport path from 'path';\n\nexport type CliConfig = {\n excludes: Array<RegExp>,\n schemaFilePath: string,\n dumpOperations?: string,\n options: ExternalOptions,\n};\n\n/**\n * This is the json-compatible form of the config\n * object.\n */\ntype JSONConfig = {\n excludes?: Array<string>,\n schemaFilePath: string,\n options?: ExternalOptions,\n dumpOperations?: string,\n};\n\nexport const loadConfigFile = (configFile: string): CliConfig => {\n // eslint-disable-next-line flowtype-errors/uncovered\n const data: JSONConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));\n const toplevelKeys = [\n 'excludes',\n 'schemaFilePath',\n 'options',\n 'dumpOperations',\n ];\n Object.keys(data).forEach((k) => {\n if (!toplevelKeys.includes(k)) {\n throw new Error(\n `Invalid attribute in config file ${configFile}: ${k}. Allowed attributes: ${toplevelKeys.join(\n ', ',\n )}`,\n );\n }\n });\n if (data.options) {\n const externalOptionsKeys = [\n 'pragma',\n 'loosePragma',\n 'ignorePragma',\n 'scalars',\n 'strictNullability',\n 'regenerateCommand',\n 'readOnlyArray',\n 'splitTypes',\n 'generatedDirectory',\n 'exportAllObjectTypes',\n 'typeFileName',\n ];\n Object.keys(data.options).forEach((k) => {\n if (!externalOptionsKeys.includes(k)) {\n throw new Error(\n `Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(\n ', ',\n )}`,\n );\n }\n });\n }\n return {\n options: data.options ?? {},\n excludes: data.excludes?.map((string) => new RegExp(string)) ?? [],\n schemaFilePath: path.join(\n path.dirname(configFile),\n data.schemaFilePath,\n ),\n dumpOperations: data.dumpOperations,\n };\n};\n\n/**\n * Loads a .json 'introspection query response', or a .graphql schema definition.\n */\nexport const getSchemas = (schemaFilePath: string): [GraphQLSchema, Schema] => {\n const raw = fs.readFileSync(schemaFilePath, 'utf8');\n if (schemaFilePath.endsWith('.graphql')) {\n const schemaForValidation = buildSchema(raw);\n const queryResponse = graphqlSync(\n schemaForValidation,\n getIntrospectionQuery({descriptions: true}),\n );\n const schemaForTypeGeneration = schemaFromIntrospectionData(\n // eslint-disable-next-line flowtype-errors/uncovered\n ((queryResponse.data: any): IntrospectionQuery),\n );\n return [schemaForValidation, schemaForTypeGeneration];\n } else {\n // eslint-disable-next-line flowtype-errors/uncovered\n const introspectionData: IntrospectionQuery = JSON.parse(raw);\n const schemaForValidation = buildClientSchema(introspectionData);\n const schemaForTypeGeneration =\n schemaFromIntrospectionData(introspectionData);\n return [schemaForValidation, schemaForTypeGeneration];\n }\n};\n"],"file":"config.js"}
package/dist/cli/run.js CHANGED
@@ -21,9 +21,11 @@ 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
+ 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); }
27
+
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; }
27
29
 
28
30
  // eslint-disable-line flowtype-errors/uncovered
29
31
 
@@ -109,6 +111,7 @@ console.log(Object.keys(resolved).length, 'resolved queries');
109
111
  /** Step (4) */
110
112
 
111
113
  let validationFailures = 0;
114
+ const printedOperations = [];
112
115
  Object.keys(resolved).forEach(k => {
113
116
  const {
114
117
  document,
@@ -122,16 +125,20 @@ Object.keys(resolved).forEach(k => {
122
125
  const hasNonFragments = document.definitions.some(({
123
126
  kind
124
127
  }) => kind !== 'FragmentDefinition');
125
- const rawSource = raw.literals[0];
128
+ const rawSource = raw.literals[0]; // eslint-disable-next-line flowtype-errors/uncovered
129
+
130
+ const withTypeNames = (0, _apolloUtilities.addTypenameToDocument)(document);
131
+ const printed = (0, _printer.print)(withTypeNames);
132
+
133
+ if (hasNonFragments && !printedOperations.includes(printed)) {
134
+ printedOperations.push(printed);
135
+ }
136
+
126
137
  const processedOptions = (0, _generateTypeFiles.processPragmas)(config.options, rawSource);
127
138
 
128
139
  if (!processedOptions) {
129
140
  return;
130
- } // eslint-disable-next-line flowtype-errors/uncovered
131
-
132
-
133
- const withTypeNames = (0, _apolloUtilities.addTypenameToDocument)(document);
134
- const printed = (0, _printer.print)(withTypeNames);
141
+ }
135
142
 
136
143
  if (hasNonFragments) {
137
144
  /* eslint-disable flowtype-errors/uncovered */
@@ -166,4 +173,13 @@ if (validationFailures) {
166
173
 
167
174
  process.exit(1);
168
175
  }
176
+
177
+ if (config.dumpOperations) {
178
+ const dumpOperations = config.dumpOperations;
179
+ const parent = (0, _path.dirname)(dumpOperations);
180
+ (0, _fs.mkdirSync)(parent, {
181
+ recursive: true
182
+ });
183
+ (0, _fs.writeFileSync)(dumpOperations, JSON.stringify(printedOperations.sort(), null, 2));
184
+ }
169
185
  //# sourceMappingURL=run.js.map
@@ -9,11 +9,12 @@ import {getSchemas, loadConfigFile} from './config';
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';
17
18
 
18
19
  /**
19
20
  * This CLI tool executes the following steps:
@@ -111,6 +112,7 @@ console.log(Object.keys(resolved).length, 'resolved queries');
111
112
  /** Step (4) */
112
113
 
113
114
  let validationFailures: number = 0;
115
+ const printedOperations: Array<string> = [];
114
116
 
115
117
  Object.keys(resolved).forEach((k) => {
116
118
  const {document, raw} = resolved[k];
@@ -121,14 +123,18 @@ Object.keys(resolved).forEach((k) => {
121
123
  ({kind}) => kind !== 'FragmentDefinition',
122
124
  );
123
125
  const rawSource: string = raw.literals[0];
124
- const processedOptions = processPragmas(config.options, rawSource);
125
- if (!processedOptions) {
126
- return;
127
- }
128
126
 
129
127
  // eslint-disable-next-line flowtype-errors/uncovered
130
128
  const withTypeNames: DocumentNode = addTypenameToDocument(document);
131
129
  const printed = print(withTypeNames);
130
+ if (hasNonFragments && !printedOperations.includes(printed)) {
131
+ printedOperations.push(printed);
132
+ }
133
+
134
+ const processedOptions = processPragmas(config.options, rawSource);
135
+ if (!processedOptions) {
136
+ return;
137
+ }
132
138
 
133
139
  if (hasNonFragments) {
134
140
  /* eslint-disable flowtype-errors/uncovered */
@@ -171,3 +177,13 @@ if (validationFailures) {
171
177
  // eslint-disable-next-line flowtype-errors/uncovered
172
178
  process.exit(1);
173
179
  }
180
+
181
+ if (config.dumpOperations) {
182
+ const dumpOperations = config.dumpOperations;
183
+ const parent = dirname(dumpOperations);
184
+ mkdirSync(parent, {recursive: true});
185
+ writeFileSync(
186
+ dumpOperations,
187
+ JSON.stringify(printedOperations.sort(), null, 2),
188
+ );
189
+ }
@@ -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","schemaForValidation","schemaForTypeGeneration","schemaFilePath","inputFiles","length","files","f","Error","filesHadErrors","Object","keys","forEach","key","file","errors","error","message","resolved","loc","validationFailures","printedOperations","k","document","raw","excludes","some","rx","test","hasNonFragments","definitions","kind","rawSource","literals","withTypeNames","printed","includes","push","processedOptions","options","err","dumpOperations","parent","recursive","JSON","stringify","sort"],"mappings":"AAAA;;AAEA;;;AACA;;AACA;;AACA;;AACA;;AAEA;;AAEA;;AACA;;AAEA;;AACA;;AACA;;;;;;AAPwD;;AAUxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AAEA,MAAMA,wBAAwB,GAAIC,IAAD,IAAiC;AAC9D,QAAMC,QAAQ,GAAG,6BACb,uFADa,EAEb;AACIC,IAAAA,QAAQ,EAAE,MADd;AAEIC,IAAAA,GAAG,EAAEH;AAFT,GAFa,CAAjB;AAOA,SAAOC,QAAQ,CACVG,IADE,GAEFC,KAFE,CAEI,IAFJ,EAGFC,GAHE,CAGGC,QAAD,IAAcC,cAAKC,IAAL,CAAUT,IAAV,EAAgBO,QAAhB,CAHhB,CAAP;AAIH,CAZD;;AAcA,MAAM,CAACG,CAAD,EAAIC,EAAJ,EAAQC,UAAR,EAAoB,GAAGC,QAAvB,IAAmCC,OAAO,CAACC,IAAjD;;AAEA,IACIH,UAAU,KAAK,IAAf,IACAA,UAAU,KAAK,QADf,IAEAA,UAAU,KAAK,MAFf,IAGA,CAACA,UAJL,EAKE;AACEI,EAAAA,OAAO,CAACC,GAAR,CAAa;AACjB;AACA,wDAFI;AAGAH,EAAAA,OAAO,CAACI,IAAR,CAAa,CAAb,EAJF,CAImB;AACpB;;AAED,MAAMC,MAAM,GAAG,4BAAeP,UAAf,CAAf;AAEA,MAAM,CAACQ,mBAAD,EAAsBC,uBAAtB,IAAiD,wBACnDF,MAAM,CAACG,cAD4C,CAAvD;AAIA,MAAMC,UAAU,GAAGV,QAAQ,CAACW,MAAT,GACbX,QADa,GAEbd,wBAAwB,CAACe,OAAO,CAACX,GAAR,EAAD,CAF9B;AAIA;;AAEA,MAAMsB,KAAK,GAAG,yBAAaF,UAAb,EAA0BG,CAAD,IAAO;AAC1C,MAAI,oBAAWA,CAAX,CAAJ,EAAmB;AACf,WAAO,sBAAaA,CAAb,EAAgB,MAAhB,CAAP;AACH;;AACD,MAAI,oBAAWA,CAAC,GAAG,KAAf,CAAJ,EAA2B;AACvB,WAAO,sBAAaA,CAAC,GAAG,KAAjB,EAAwB,MAAxB,CAAP;AACH;;AACD,QAAM,IAAIC,KAAJ,CAAW,kBAAiBD,CAAE,EAA9B,CAAN;AACH,CARa,CAAd;AAUA,IAAIE,cAAc,GAAG,KAArB;AACAC,MAAM,CAACC,IAAP,CAAYL,KAAZ,EAAmBM,OAAnB,CAA4BC,GAAD,IAAS;AAChC,QAAMC,IAAI,GAAGR,KAAK,CAACO,GAAD,CAAlB;;AACA,MAAIC,IAAI,CAACC,MAAL,CAAYV,MAAhB,EAAwB;AACpBI,IAAAA,cAAc,GAAG,IAAjB;AACAZ,IAAAA,OAAO,CAACmB,KAAR,CAAe,aAAYF,IAAI,CAACzB,IAAK,EAArC;AACAyB,IAAAA,IAAI,CAACC,MAAL,CAAYH,OAAZ,CAAqBI,KAAD,IAAW;AAC3BnB,MAAAA,OAAO,CAACmB,KAAR,CAAe,MAAKA,KAAK,CAACC,OAAQ,EAAlC;AACH,KAFD;AAGH;AACJ,CATD;;AAWA,IAAIR,cAAJ,EAAoB;AAChBZ,EAAAA,OAAO,CAACmB,KAAR,CAAc,UAAd;AACArB,EAAAA,OAAO,CAACI,IAAR,CAAa,CAAb,EAFgB,CAEC;AACpB;AAED;;;AAEA,MAAM;AAACmB,EAAAA,QAAD;AAAWH,EAAAA;AAAX,IAAqB,+BAAiBT,KAAjB,CAA3B;;AACA,IAAIS,MAAM,CAACV,MAAX,EAAmB;AACfU,EAAAA,MAAM,CAACH,OAAP,CAAgBI,KAAD,IAAW;AACtBnB,IAAAA,OAAO,CAACmB,KAAR,CAAe,oBAAmBA,KAAK,CAACC,OAAQ,OAAMD,KAAK,CAACG,GAAN,CAAU9B,IAAK,EAArE;AACH,GAFD;AAGAQ,EAAAA,OAAO,CAACmB,KAAR,CAAc,UAAd;AACArB,EAAAA,OAAO,CAACI,IAAR,CAAa,CAAb,EALe,CAKE;AACpB;;AAEDF,OAAO,CAACC,GAAR,CAAYY,MAAM,CAACC,IAAP,CAAYO,QAAZ,EAAsBb,MAAlC,EAA0C,kBAA1C;AAEA;;AAEA,IAAIe,kBAA0B,GAAG,CAAjC;AACA,MAAMC,iBAAgC,GAAG,EAAzC;AAEAX,MAAM,CAACC,IAAP,CAAYO,QAAZ,EAAsBN,OAAtB,CAA+BU,CAAD,IAAO;AACjC,QAAM;AAACC,IAAAA,QAAD;AAAWC,IAAAA;AAAX,MAAkBN,QAAQ,CAACI,CAAD,CAAhC;;AACA,MAAItB,MAAM,CAACyB,QAAP,CAAgBC,IAAhB,CAAsBC,EAAD,IAAQA,EAAE,CAACC,IAAH,CAAQJ,GAAG,CAACL,GAAJ,CAAQ9B,IAAhB,CAA7B,CAAJ,EAAyD;AACrD,WADqD,CAC7C;AACX;;AACD,QAAMwC,eAAe,GAAGN,QAAQ,CAACO,WAAT,CAAqBJ,IAArB,CACpB,CAAC;AAACK,IAAAA;AAAD,GAAD,KAAYA,IAAI,KAAK,oBADD,CAAxB;AAGA,QAAMC,SAAiB,GAAGR,GAAG,CAACS,QAAJ,CAAa,CAAb,CAA1B,CARiC,CAUjC;;AACA,QAAMC,aAA2B,GAAG,4CAAsBX,QAAtB,CAApC;AACA,QAAMY,OAAO,GAAG,oBAAMD,aAAN,CAAhB;;AACA,MAAIL,eAAe,IAAI,CAACR,iBAAiB,CAACe,QAAlB,CAA2BD,OAA3B,CAAxB,EAA6D;AACzDd,IAAAA,iBAAiB,CAACgB,IAAlB,CAAuBF,OAAvB;AACH;;AAED,QAAMG,gBAAgB,GAAG,uCAAetC,MAAM,CAACuC,OAAtB,EAA+BP,SAA/B,CAAzB;;AACA,MAAI,CAACM,gBAAL,EAAuB;AACnB;AACH;;AAED,MAAIT,eAAJ,EAAqB;AACjB;AACA,UAAMd,MAAM,GAAG,0BAASd,mBAAT,EAA8BiC,aAA9B,CAAf;AACA;;AACA,QAAInB,MAAM,CAACV,MAAX,EAAmB;AACfU,MAAAA,MAAM,CAACH,OAAP,CAAgBI,KAAD,IAAW;AACtBnB,QAAAA,OAAO,CAACmB,KAAR,CACK,sCAAqCQ,GAAG,CAACL,GAAJ,CAAQ9B,IAAK,GADvD;AAGAQ,QAAAA,OAAO,CAACmB,KAAR,CAAcmB,OAAd;AACAtC,QAAAA,OAAO,CAACmB,KAAR,CAAcA,KAAd;AACAI,QAAAA,kBAAkB;AACrB,OAPD;AAQH;AACD;;AACH;;AAED,MAAI;AACA,8CACII,GAAG,CAACL,GAAJ,CAAQ9B,IADZ,EAEIa,uBAFJ,EAGIgC,aAHJ,EAIII,gBAJJ,EADA,CAOA;AACH,GARD,CAQE,OAAOE,GAAP,EAAY;AACV3C,IAAAA,OAAO,CAACmB,KAAR,CAAe,yCAAwCQ,GAAG,CAACL,GAAJ,CAAQ9B,IAAK,EAApE;AACAQ,IAAAA,OAAO,CAACmB,KAAR,CAAcmB,OAAd,EAFU,CAGV;;AACAtC,IAAAA,OAAO,CAACmB,KAAR,CAAcwB,GAAd;AACApB,IAAAA,kBAAkB;AACrB;AACJ,CAtDD;;AAwDA,IAAIA,kBAAJ,EAAwB;AACpBvB,EAAAA,OAAO,CAACmB,KAAR,CACK,eAAcI,kBAAmB,4CADtC,EADoB,CAIpB;;AACAzB,EAAAA,OAAO,CAACI,IAAR,CAAa,CAAb;AACH;;AAED,IAAIC,MAAM,CAACyC,cAAX,EAA2B;AACvB,QAAMA,cAAc,GAAGzC,MAAM,CAACyC,cAA9B;AACA,QAAMC,MAAM,GAAG,mBAAQD,cAAR,CAAf;AACA,qBAAUC,MAAV,EAAkB;AAACC,IAAAA,SAAS,EAAE;AAAZ,GAAlB;AACA,yBACIF,cADJ,EAEIG,IAAI,CAACC,SAAL,CAAexB,iBAAiB,CAACyB,IAAlB,EAAf,EAAyC,IAAzC,EAA+C,CAA/C,CAFJ;AAIH","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, 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';\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;\nconst printedOperations: Array<string> = [];\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\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(config.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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/graphql-flow",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "bin": {
5
5
  "graphql-flow": "./dist/cli/run.js"
6
6
  },
package/src/cli/config.js CHANGED
@@ -18,6 +18,7 @@ import path from 'path';
18
18
  export type CliConfig = {
19
19
  excludes: Array<RegExp>,
20
20
  schemaFilePath: string,
21
+ dumpOperations?: string,
21
22
  options: ExternalOptions,
22
23
  };
23
24
 
@@ -29,12 +30,18 @@ type JSONConfig = {
29
30
  excludes?: Array<string>,
30
31
  schemaFilePath: string,
31
32
  options?: ExternalOptions,
33
+ dumpOperations?: string,
32
34
  };
33
35
 
34
36
  export const loadConfigFile = (configFile: string): CliConfig => {
35
37
  // eslint-disable-next-line flowtype-errors/uncovered
36
38
  const data: JSONConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));
37
- const toplevelKeys = ['excludes', 'schemaFilePath', 'options'];
39
+ const toplevelKeys = [
40
+ 'excludes',
41
+ 'schemaFilePath',
42
+ 'options',
43
+ 'dumpOperations',
44
+ ];
38
45
  Object.keys(data).forEach((k) => {
39
46
  if (!toplevelKeys.includes(k)) {
40
47
  throw new Error(
@@ -75,6 +82,7 @@ export const loadConfigFile = (configFile: string): CliConfig => {
75
82
  path.dirname(configFile),
76
83
  data.schemaFilePath,
77
84
  ),
85
+ dumpOperations: data.dumpOperations,
78
86
  };
79
87
  };
80
88
 
package/src/cli/run.js CHANGED
@@ -9,11 +9,12 @@ import {getSchemas, loadConfigFile} from './config';
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';
17
18
 
18
19
  /**
19
20
  * This CLI tool executes the following steps:
@@ -111,6 +112,7 @@ console.log(Object.keys(resolved).length, 'resolved queries');
111
112
  /** Step (4) */
112
113
 
113
114
  let validationFailures: number = 0;
115
+ const printedOperations: Array<string> = [];
114
116
 
115
117
  Object.keys(resolved).forEach((k) => {
116
118
  const {document, raw} = resolved[k];
@@ -121,14 +123,18 @@ Object.keys(resolved).forEach((k) => {
121
123
  ({kind}) => kind !== 'FragmentDefinition',
122
124
  );
123
125
  const rawSource: string = raw.literals[0];
124
- const processedOptions = processPragmas(config.options, rawSource);
125
- if (!processedOptions) {
126
- return;
127
- }
128
126
 
129
127
  // eslint-disable-next-line flowtype-errors/uncovered
130
128
  const withTypeNames: DocumentNode = addTypenameToDocument(document);
131
129
  const printed = print(withTypeNames);
130
+ if (hasNonFragments && !printedOperations.includes(printed)) {
131
+ printedOperations.push(printed);
132
+ }
133
+
134
+ const processedOptions = processPragmas(config.options, rawSource);
135
+ if (!processedOptions) {
136
+ return;
137
+ }
132
138
 
133
139
  if (hasNonFragments) {
134
140
  /* eslint-disable flowtype-errors/uncovered */
@@ -171,3 +177,13 @@ if (validationFailures) {
171
177
  // eslint-disable-next-line flowtype-errors/uncovered
172
178
  process.exit(1);
173
179
  }
180
+
181
+ if (config.dumpOperations) {
182
+ const dumpOperations = config.dumpOperations;
183
+ const parent = dirname(dumpOperations);
184
+ mkdirSync(parent, {recursive: true});
185
+ writeFileSync(
186
+ dumpOperations,
187
+ JSON.stringify(printedOperations.sort(), null, 2),
188
+ );
189
+ }