@khanacademy/graphql-flow 0.1.0 → 0.2.2

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/.babelrc CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "presets": [
3
3
  "@babel/preset-flow",
4
- ["@babel/preset-env", { "targets": { "node": "16" } }]
4
+ ["@babel/preset-env", { "targets": { "node": "12" } }]
5
5
  ]
6
6
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @khanacademy/graphql-flow
2
2
 
3
+ ## 0.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 31dd235: Compile for node 12 instead of 16
8
+
9
+ ## 0.2.1
10
+
11
+ ### Patch Changes
12
+
13
+ - e8a8025: Add shebang to the exported binary, so that it runs
14
+
15
+ ## 0.2.0
16
+
17
+ ### Minor Changes
18
+
19
+ - d9a8229: Generate types for fragments!
20
+
21
+ ### Patch Changes
22
+
23
+ - 7497164: Fix a bug in index file generation that resulted in duplicate entries
24
+ - 26abf9b: Add options for specifying the name of the generated directory, and for exporting the response and variables types.
25
+
3
26
  ## 0.1.0
4
27
 
5
28
  ### Minor Changes
package/Readme.md CHANGED
@@ -42,6 +42,15 @@ type Options = {
42
42
  readOnlyArray: boolean = true,
43
43
  scalars: {[key: string]: 'string' | 'boolean' | 'number'}
44
44
 
45
+ // Specify the name of the generated types directory
46
+ generatedDirectory: string = '__generated__',
47
+
48
+ // The default generated type contains both the types of the response
49
+ // and the variables, combined as [operatioName]Type. Setting
50
+ // `splitTypes = true` adds the additional exports [operationName]
51
+ // (for the response) and [operationName]Variables (for the variables).
52
+ splitTypes?: boolean,
53
+
45
54
  // Specify an opt-in pragma that must be present in a graphql string source
46
55
  // in order for it to be picked up and processed
47
56
  // e.g. set this to `"# @autogen\n"` to only generate types for queries that
@@ -55,6 +64,12 @@ type Options = {
55
64
 
56
65
  // Any graphql operations containing ignorePragma will be skipped
57
66
  ignorePragma?: string,
67
+
68
+ // Set to true to mirror gqlgen's behavior of exporting all
69
+ // nested object types within the response type.
70
+ // Names are generated by concatenating the attribute names
71
+ // of the path to the object type, separated by underscores.
72
+ exportAllObjectTypes?: boolean,
58
73
  }
59
74
  ```
60
75
 
@@ -16,7 +16,7 @@ var _path = _interopRequireDefault(require("path"));
16
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
17
 
18
18
  const loadConfigFile = configFile => {
19
- var _data$excludes;
19
+ var _data$options, _data$excludes$map, _data$excludes;
20
20
 
21
21
  // eslint-disable-next-line flowtype-errors/uncovered
22
22
  const data = JSON.parse(_fs.default.readFileSync(configFile, 'utf8'));
@@ -28,7 +28,7 @@ const loadConfigFile = configFile => {
28
28
  });
29
29
 
30
30
  if (data.options) {
31
- const externalOptionsKeys = ['pragma', 'loosePragma', 'ignorePragma', 'scalars', 'strictNullability', 'regenerateCommand', 'readOnlyArray'];
31
+ const externalOptionsKeys = ['pragma', 'loosePragma', 'ignorePragma', 'scalars', 'strictNullability', 'regenerateCommand', 'readOnlyArray', 'splitTypes', 'generatedDirectory', 'exportAllObjectTypes'];
32
32
  Object.keys(data.options).forEach(k => {
33
33
  if (!externalOptionsKeys.includes(k)) {
34
34
  throw new Error(`Invalid option in config file ${configFile}: ${k}. Allowed options: ${externalOptionsKeys.join(', ')}`);
@@ -37,8 +37,8 @@ const loadConfigFile = configFile => {
37
37
  }
38
38
 
39
39
  return {
40
- options: data.options ?? {},
41
- excludes: ((_data$excludes = data.excludes) === null || _data$excludes === void 0 ? void 0 : _data$excludes.map(string => new RegExp(string))) ?? [],
40
+ options: (_data$options = data.options) !== null && _data$options !== void 0 ? _data$options : {},
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
42
  schemaFilePath: _path.default.join(_path.default.dirname(configFile), data.schemaFilePath)
43
43
  };
44
44
  };
@@ -53,6 +53,9 @@ export const loadConfigFile = (configFile: string): CliConfig => {
53
53
  'strictNullability',
54
54
  'regenerateCommand',
55
55
  'readOnlyArray',
56
+ 'splitTypes',
57
+ 'generatedDirectory',
58
+ 'exportAllObjectTypes',
56
59
  ];
57
60
  Object.keys(data.options).forEach((k) => {
58
61
  if (!externalOptionsKeys.includes(k)) {
@@ -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,CAA5B;AASAR,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,EAAEb,IAAI,CAACa,OAAL,IAAgB,EADtB;AAEHE,IAAAA,QAAQ,EAAE,mBAAAf,IAAI,CAACe,QAAL,kEAAeC,GAAf,CAAoBC,MAAD,IAAY,IAAIC,MAAJ,CAAWD,MAAX,CAA/B,MAAsD,EAF7D;AAGHE,IAAAA,cAAc,EAAEC,cAAKR,IAAL,CACZQ,cAAKC,OAAL,CAAatB,UAAb,CADY,EAEZC,IAAI,CAACmB,cAFO;AAHb,GAAP;AAQH,CAzCM;AA2CP;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 ];\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","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,CAA5B;AAYAR,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,CA5CM;AA8CP;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 ];\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"}
package/dist/cli/run.js CHANGED
@@ -1,3 +1,6 @@
1
+ #!/usr/bin/env node
2
+
3
+ /* eslint-disable no-console */
1
4
  "use strict";
2
5
 
3
6
  var _generateTypeFiles = require("../generateTypeFiles");
@@ -22,7 +25,6 @@ var _path = _interopRequireDefault(require("path"));
22
25
 
23
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
27
 
25
- /* eslint-disable no-console */
26
28
  // eslint-disable-line flowtype-errors/uncovered
27
29
 
28
30
  /**
@@ -113,28 +115,30 @@ Object.keys(resolved).forEach(k => {
113
115
  const rawSource = raw.literals[0];
114
116
  const processedOptions = (0, _generateTypeFiles.processPragmas)(config.options, rawSource);
115
117
 
116
- if (!hasNonFragments || !processedOptions) {
118
+ if (!processedOptions) {
117
119
  return;
118
120
  } // eslint-disable-next-line flowtype-errors/uncovered
119
121
 
120
122
 
121
123
  const withTypeNames = (0, _apolloUtilities.addTypenameToDocument)(document);
122
124
  const printed = (0, _printer.print)(withTypeNames);
123
- /* eslint-disable flowtype-errors/uncovered */
124
125
 
125
- const errors = (0, _validation.validate)(schemaForValidation, withTypeNames);
126
- /* eslint-disable flowtype-errors/uncovered */
126
+ if (hasNonFragments) {
127
+ /* eslint-disable flowtype-errors/uncovered */
128
+ const errors = (0, _validation.validate)(schemaForValidation, withTypeNames);
129
+ /* eslint-disable flowtype-errors/uncovered */
130
+
131
+ if (errors.length) {
132
+ errors.forEach(error => {
133
+ console.error(`Schema validation found errors for ${raw.loc.path}!`);
134
+ console.error(printed);
135
+ console.error(error);
136
+ validationFailures++;
137
+ });
138
+ }
139
+ /* eslint-enable flowtype-errors/uncovered */
127
140
 
128
- if (errors.length) {
129
- errors.forEach(error => {
130
- console.error(`Schema validation found errors for ${raw.loc.path}!`);
131
- console.error(printed);
132
- console.error(error);
133
- validationFailures++;
134
- });
135
141
  }
136
- /* eslint-enable flowtype-errors/uncovered */
137
-
138
142
 
139
143
  try {
140
144
  (0, _generateTypeFiles.generateTypeFiles)(raw.loc.path, schemaForTypeGeneration, withTypeNames, processedOptions); // eslint-disable-next-line flowtype-errors/uncovered
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  // @flow
2
3
  /* eslint-disable no-console */
3
4
  import {generateTypeFiles, processPragmas} from '../generateTypeFiles';
@@ -113,27 +114,30 @@ Object.keys(resolved).forEach((k) => {
113
114
  );
114
115
  const rawSource: string = raw.literals[0];
115
116
  const processedOptions = processPragmas(config.options, rawSource);
116
- if (!hasNonFragments || !processedOptions) {
117
+ if (!processedOptions) {
117
118
  return;
118
119
  }
119
120
 
120
121
  // eslint-disable-next-line flowtype-errors/uncovered
121
122
  const withTypeNames: DocumentNode = addTypenameToDocument(document);
122
123
  const printed = print(withTypeNames);
123
- /* eslint-disable flowtype-errors/uncovered */
124
- const errors = validate(schemaForValidation, withTypeNames);
125
- /* eslint-disable flowtype-errors/uncovered */
126
- if (errors.length) {
127
- errors.forEach((error) => {
128
- console.error(
129
- `Schema validation found errors for ${raw.loc.path}!`,
130
- );
131
- console.error(printed);
132
- console.error(error);
133
- validationFailures++;
134
- });
124
+
125
+ if (hasNonFragments) {
126
+ /* eslint-disable flowtype-errors/uncovered */
127
+ const errors = validate(schemaForValidation, withTypeNames);
128
+ /* eslint-disable flowtype-errors/uncovered */
129
+ if (errors.length) {
130
+ errors.forEach((error) => {
131
+ console.error(
132
+ `Schema validation found errors for ${raw.loc.path}!`,
133
+ );
134
+ console.error(printed);
135
+ console.error(error);
136
+ validationFailures++;
137
+ });
138
+ }
139
+ /* eslint-enable flowtype-errors/uncovered */
135
140
  }
136
- /* eslint-enable flowtype-errors/uncovered */
137
141
 
138
142
  try {
139
143
  generateTypeFiles(
@@ -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","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":["// @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 {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) => readFileSync(f, 'utf8'));\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 (!hasNonFragments || !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 /* 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 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","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 {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) => readFileSync(f, 'utf8'));\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"}
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.unionOrInterfaceToFlow = exports.typeToFlow = exports.objectPropertiesToFlow = exports.generateResponseType = void 0;
6
+ exports.unionOrInterfaceToFlow = exports.typeToFlow = exports.objectPropertiesToFlow = exports.generateResponseType = exports.generateFragmentType = void 0;
7
7
 
8
8
  var _generator = _interopRequireDefault(require("@babel/generator"));
9
9
 
@@ -29,6 +29,55 @@ const generateResponseType = (schema, query, config) => {
29
29
 
30
30
  exports.generateResponseType = generateResponseType;
31
31
 
32
+ const sortedObjectTypeAnnotation = (config, properties) => {
33
+ const obj = babelTypes.objectTypeAnnotation(properties.sort((a, b) => {
34
+ if (a.type === 'ObjectTypeProperty' && b.type === 'ObjectTypeProperty') {
35
+ const aName = a.key.type === 'Identifier' ? a.key.name : '';
36
+ const bName = b.key.type === 'Identifier' ? b.key.name : '';
37
+ return aName < bName ? -1 : 1;
38
+ }
39
+
40
+ return 0;
41
+ }), undefined
42
+ /* indexers */
43
+ , undefined
44
+ /* callProperties */
45
+ , undefined
46
+ /* internalSlots */
47
+ , true
48
+ /* exact */
49
+ );
50
+ const name = config.path.join('_');
51
+ const isTopLevelType = config.path.length <= 1;
52
+
53
+ if (config.allObjectTypes != null && !isTopLevelType) {
54
+ config.allObjectTypes[name] = obj;
55
+ return babelTypes.genericTypeAnnotation(babelTypes.identifier(name));
56
+ } else {
57
+ return obj;
58
+ }
59
+ };
60
+
61
+ const generateFragmentType = (schema, fragment, config) => {
62
+ const onType = fragment.typeCondition.name.value;
63
+ let ast;
64
+
65
+ if (schema.typesByName[onType]) {
66
+ ast = sortedObjectTypeAnnotation(config, objectPropertiesToFlow(config, schema.typesByName[onType], onType, fragment.selectionSet.selections));
67
+ } else if (schema.interfacesByName[onType]) {
68
+ ast = unionOrInterfaceToFlow(config, config.schema.interfacesByName[onType], fragment.selectionSet.selections);
69
+ } else if (schema.unionsByName[onType]) {
70
+ ast = unionOrInterfaceToFlow(config, config.schema.unionsByName[onType], fragment.selectionSet.selections);
71
+ } else {
72
+ throw new Error(`Unknown ${onType}`);
73
+ } // eslint-disable-next-line flowtype-errors/uncovered
74
+
75
+
76
+ return (0, _generator.default)(ast).code;
77
+ };
78
+
79
+ exports.generateFragmentType = generateFragmentType;
80
+
32
81
  const _typeToFlow = (config, type, selection) => {
33
82
  if (type.kind === 'SCALAR') {
34
83
  return (0, _enums.scalarTypeToFlow)(config, type.name);
@@ -103,30 +152,32 @@ const typeToFlow = (config, type, selection) => {
103
152
 
104
153
  exports.typeToFlow = typeToFlow;
105
154
 
106
- const querySelectionToObjectType = (config, selections, type, typeName) => {
155
+ const ensureOnlyOneTypenameProperty = properties => {
107
156
  let seenTypeName = false;
108
- return babelTypes.objectTypeAnnotation(objectPropertiesToFlow(config, type, typeName, selections).filter(type => {
157
+ return properties.filter(type => {
109
158
  // The apollo-utilities "addTypeName" utility will add it
110
159
  // even if it's already specified :( so we have to filter out
111
160
  // the extra one here.
112
161
  if (type.type === 'ObjectTypeProperty' && type.key.name === '__typename') {
162
+ const name = type.value.type === 'StringLiteralTypeAnnotation' ? type.value.value : 'INVALID';
163
+
113
164
  if (seenTypeName) {
165
+ if (name !== seenTypeName) {
166
+ throw new Error(`Got two different type names ${name}, ${seenTypeName}`);
167
+ }
168
+
114
169
  return false;
115
170
  }
116
171
 
117
- seenTypeName = true;
172
+ seenTypeName = name;
118
173
  }
119
174
 
120
175
  return true;
121
- }), undefined
122
- /* indexers */
123
- , undefined
124
- /* callProperties */
125
- , undefined
126
- /* internalSlots */
127
- , true
128
- /* exact */
129
- );
176
+ });
177
+ };
178
+
179
+ const querySelectionToObjectType = (config, selections, type, typeName) => {
180
+ return sortedObjectTypeAnnotation(config, ensureOnlyOneTypenameProperty(objectPropertiesToFlow(config, type, typeName, selections)));
130
181
  };
131
182
 
132
183
  const objectPropertiesToFlow = (config, type, typeName, selections) => {
@@ -134,9 +185,14 @@ const objectPropertiesToFlow = (config, type, typeName, selections) => {
134
185
  switch (selection.kind) {
135
186
  case 'InlineFragment':
136
187
  {
137
- var _selection$typeCondit;
188
+ var _selection$typeCondit, _selection$typeCondit2;
189
+
190
+ const newTypeName = (_selection$typeCondit = (_selection$typeCondit2 = selection.typeCondition) === null || _selection$typeCondit2 === void 0 ? void 0 : _selection$typeCondit2.name.value) !== null && _selection$typeCondit !== void 0 ? _selection$typeCondit : typeName;
191
+
192
+ if (newTypeName !== typeName) {
193
+ return [];
194
+ }
138
195
 
139
- const newTypeName = ((_selection$typeCondit = selection.typeCondition) === null || _selection$typeCondit === void 0 ? void 0 : _selection$typeCondit.name.value) ?? typeName;
140
196
  return objectPropertiesToFlow(config, config.schema.typesByName[newTypeName], newTypeName, selection.selectionSet.selections);
141
197
  }
142
198
 
@@ -162,7 +218,9 @@ const objectPropertiesToFlow = (config, type, typeName, selections) => {
162
218
  }
163
219
 
164
220
  const typeField = type.fieldsByName[name];
165
- return [(0, _utils.maybeAddDescriptionComment)(typeField.description, (0, _utils.liftLeadingPropertyComments)(babelTypes.objectTypeProperty(babelTypes.identifier(alias), typeToFlow(config, typeField.type, selection))))];
221
+ return [(0, _utils.maybeAddDescriptionComment)(typeField.description, (0, _utils.liftLeadingPropertyComments)(babelTypes.objectTypeProperty(babelTypes.identifier(alias), typeToFlow({ ...config,
222
+ path: config.path.concat([alias])
223
+ }, typeField.type, selection))))];
166
224
 
167
225
  default:
168
226
  config.errors.push( // eslint-disable-next-line flowtype-errors/uncovered
@@ -175,46 +233,80 @@ const objectPropertiesToFlow = (config, type, typeName, selections) => {
175
233
  exports.objectPropertiesToFlow = objectPropertiesToFlow;
176
234
 
177
235
  const unionOrInterfaceToFlow = (config, type, selections) => {
178
- const selectedAttributes = type.possibleTypes.map(possible => {
179
- let seenTypeName = false;
180
- return selections.map(selection => unionOrInterfaceSelection(config, type, possible, selection)).flat().filter(type => {
181
- // The apollo-utilities "addTypeName" utility will add it
182
- // even if it's already specified :( so we have to filter out
183
- // the extra one here.
184
- if (type.type === 'ObjectTypeProperty' && type.key.name === '__typename') {
185
- if (seenTypeName) {
186
- return false;
187
- }
188
-
189
- seenTypeName = true;
190
- }
191
-
192
- return true;
193
- });
194
- });
195
236
  const allFields = selections.every(selection => selection.kind === 'Field');
237
+ const selectedAttributes = type.possibleTypes.slice().sort((a, b) => {
238
+ return a.name < b.name ? -1 : 1;
239
+ }).map(possible => {
240
+ const configWithUpdatedPath = { ...config,
241
+ path: allFields ? config.path : config.path.concat([possible.name])
242
+ };
243
+ return {
244
+ typeName: possible.name,
245
+ attributes: ensureOnlyOneTypenameProperty(selections.map(selection => unionOrInterfaceSelection(configWithUpdatedPath, type, possible, selection)).flat())
246
+ };
247
+ }); // If they're all fields, the only selection that could be different is __typename
248
+
249
+ if (allFields) {
250
+ const sharedAttributes = selectedAttributes[0].attributes.slice();
251
+ const typeNameIndex = selectedAttributes[0].attributes.findIndex(x => x.type === 'ObjectTypeProperty' && x.key.type === 'Identifier' && x.key.name === '__typename');
252
+
253
+ if (typeNameIndex !== -1) {
254
+ sharedAttributes[typeNameIndex] = babelTypes.objectTypeProperty(babelTypes.identifier('__typename'), babelTypes.unionTypeAnnotation(selectedAttributes.map(attrs => // eslint-disable-next-line flowtype-errors/uncovered
255
+ attrs.attributes[typeNameIndex].value)));
256
+ }
196
257
 
197
- if (selectedAttributes.length === 1 || allFields) {
198
- return babelTypes.objectTypeAnnotation(selectedAttributes[0], undefined
199
- /* indexers */
200
- , undefined
201
- /* callProperties */
202
- , undefined
203
- /* internalSlots */
204
- , true
205
- /* exact */
206
- );
258
+ return sortedObjectTypeAnnotation(config, sharedAttributes);
207
259
  }
208
260
 
209
- return babelTypes.unionTypeAnnotation(selectedAttributes.map(properties => babelTypes.objectTypeAnnotation(properties, undefined
210
- /* indexers */
211
- , undefined
212
- /* callProperties */
213
- , undefined
214
- /* internalSlots */
215
- , true
216
- /* exact */
217
- )));
261
+ if (selectedAttributes.length === 1) {
262
+ return sortedObjectTypeAnnotation(config, selectedAttributes[0].attributes);
263
+ }
264
+ /**
265
+ * When generating the objects for the sub-options of a union, the path needs
266
+ * to include the name of the object type.
267
+ * ```
268
+ * query getFriend {
269
+ * friend {
270
+ * ... on Human { id }
271
+ * ... on Droid { arms }
272
+ * }
273
+ * }
274
+ * ```
275
+ * produces
276
+ * ```
277
+ * type getFriend = {friend: getFriend_friend_Human | getFriend_friend_Droid }
278
+ * type getFriend_friend_Human = {id: string}
279
+ * type getFriend_friend_Droid = {arms: number}
280
+ * ```
281
+ * Note that this is different from when an attribute has a plain object type.
282
+ * ```
283
+ * query getHuman {
284
+ * me: human(id: "me") { id }
285
+ * }
286
+ * ```
287
+ * produces
288
+ * ```
289
+ * type getHuman = {me: getHuman_me}
290
+ * type getHuman_me = {id: string}
291
+ * ```
292
+ * instead of e.g. `getHuman_me_Human`.
293
+ */
294
+
295
+
296
+ const result = babelTypes.unionTypeAnnotation(selectedAttributes.map(({
297
+ typeName,
298
+ attributes
299
+ }) => sortedObjectTypeAnnotation({ ...config,
300
+ path: config.path.concat([typeName])
301
+ }, attributes)));
302
+ const name = config.path.join('_');
303
+
304
+ if (config.allObjectTypes && config.path.length > 1) {
305
+ config.allObjectTypes[name] = result;
306
+ return babelTypes.genericTypeAnnotation(babelTypes.identifier(name));
307
+ }
308
+
309
+ return result;
218
310
  };
219
311
 
220
312
  exports.unionOrInterfaceToFlow = unionOrInterfaceToFlow;
@@ -236,11 +328,18 @@ const unionOrInterfaceSelection = (config, type, possible, selection) => {
236
328
  }
237
329
 
238
330
  const typeField = type.fieldsByName[name];
239
- return [(0, _utils.liftLeadingPropertyComments)(babelTypes.objectTypeProperty(babelTypes.identifier(alias), typeToFlow(config, typeField.type, selection)))];
331
+ return [(0, _utils.liftLeadingPropertyComments)(babelTypes.objectTypeProperty(babelTypes.identifier(alias), typeToFlow({ ...config,
332
+ path: config.path.concat([name])
333
+ }, typeField.type, selection)))];
240
334
  }
241
335
 
242
336
  if (selection.kind === 'FragmentSpread') {
243
337
  const fragment = config.fragments[selection.name.value];
338
+
339
+ if (!fragment) {
340
+ throw new Error(`Unknown fragment ${selection.name.value}`);
341
+ }
342
+
244
343
  const typeName = fragment.typeCondition.name.value;
245
344
 
246
345
  if (config.schema.interfacesByName[typeName] && config.schema.interfacesByName[typeName].possibleTypesByName[possible.name] || typeName === possible.name) {