relay-compiler 1.5.0-rc.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay v1.5.0-rc.1
2
+ * Relay v1.5.0
3
3
  *
4
4
  * Copyright (c) 2013-present, Facebook, Inc.
5
5
  *
package/lib/ASTCache.js CHANGED
@@ -43,6 +43,11 @@ var ASTCache = function () {
43
43
  var documents = ImmutableMap();
44
44
 
45
45
  files.forEach(function (file) {
46
+ if (!file.exists) {
47
+ _this._documents['delete'](file.relPath);
48
+ return;
49
+ }
50
+
46
51
  var doc = function () {
47
52
  try {
48
53
  return _this._parse(_this._baseDir, file);
package/lib/ASTConvert.js CHANGED
@@ -16,7 +16,7 @@ var _toConsumableArray3 = _interopRequireDefault(require('babel-runtime/helpers/
16
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17
17
 
18
18
  var _require = require('./GraphQLSchemaUtils'),
19
- isOperationDefinitionAST = _require.isOperationDefinitionAST,
19
+ isExecutableDefinitionAST = _require.isExecutableDefinitionAST,
20
20
  isSchemaDefinitionAST = _require.isSchemaDefinitionAST;
21
21
 
22
22
  var _require2 = require('graphql'),
@@ -31,7 +31,7 @@ function convertASTDocuments(schema, documents, validationRules, transform) {
31
31
  var astDefinitions = [];
32
32
  documents.forEach(function (doc) {
33
33
  doc.definitions.forEach(function (definition) {
34
- if (isOperationDefinitionAST(definition)) {
34
+ if (isExecutableDefinitionAST(definition)) {
35
35
  astDefinitions.push(definition);
36
36
  }
37
37
  });
@@ -49,7 +49,7 @@ function convertASTDocumentsWithBase(schema, baseDocuments, documents, validatio
49
49
  var requiredDefinitions = new Map();
50
50
  var baseMap = new Map();
51
51
  baseDefinitions.forEach(function (definition) {
52
- if (isOperationDefinitionAST(definition)) {
52
+ if (isExecutableDefinitionAST(definition)) {
53
53
  var definitionName = definition.name && definition.name.value;
54
54
  // If there's no name, no reason to put in the map
55
55
  if (definitionName) {
@@ -63,7 +63,7 @@ function convertASTDocumentsWithBase(schema, baseDocuments, documents, validatio
63
63
 
64
64
  var definitionsToVisit = [];
65
65
  definitions.forEach(function (definition) {
66
- if (isOperationDefinitionAST(definition)) {
66
+ if (isExecutableDefinitionAST(definition)) {
67
67
  definitionsToVisit.push(definition);
68
68
  }
69
69
  });
@@ -103,7 +103,7 @@ function convertASTDocumentsWithBase(schema, baseDocuments, documents, validatio
103
103
  function convertASTDefinitions(schema, definitions, validationRules, transform) {
104
104
  var operationDefinitions = [];
105
105
  definitions.forEach(function (definition) {
106
- if (isOperationDefinitionAST(definition)) {
106
+ if (isExecutableDefinitionAST(definition)) {
107
107
  operationDefinitions.push(definition);
108
108
  }
109
109
  });
@@ -56,7 +56,15 @@ var CodegenDirectory = function () {
56
56
  if (require('fs').existsSync(dir)) {
57
57
  require('fbjs/lib/invariant')(require('fs').statSync(dir).isDirectory(), 'Expected `%s` to be a directory.', dir);
58
58
  } else if (!this.onlyValidate) {
59
- require('fs').mkdirSync(dir);
59
+ var dirs = [dir];
60
+ var parent = require('path').dirname(dir);
61
+ while (!require('fs').existsSync(parent)) {
62
+ dirs.unshift(parent);
63
+ parent = require('path').dirname(parent);
64
+ }
65
+ dirs.forEach(function (d) {
66
+ return require('fs').mkdirSync(d);
67
+ });
60
68
  }
61
69
  this._files = new Set();
62
70
  this.changes = {
@@ -240,8 +240,7 @@ var CodegenRunner = function () {
240
240
 
241
241
  return require('./GraphQLCompilerProfiler').asyncContext('CodegenRunner.write', (0, _asyncToGenerator3.default)(function* () {
242
242
  try {
243
- // eslint-disable-next-line no-console
244
- console.log('\nWriting %s', writerName);
243
+ _this5._reporter.reportMessage('\nWriting ' + writerName);
245
244
  var _writerConfigs$writer = _this5.writerConfigs[writerName],
246
245
  _getWriter = _writerConfigs$writer.getWriter,
247
246
  _parser2 = _writerConfigs$writer.parser,
@@ -391,16 +390,14 @@ var CodegenRunner = function () {
391
390
  } catch (error) {
392
391
  _this6._reporter.reportError('CodegenRunner.watch', error);
393
392
  }
394
- // eslint-disable-next-line no-console
395
- console.log('Watching for changes to %s...', parserName);
393
+ _this6._reporter.reportMessage('Watching for changes to ' + parserName + '...');
396
394
  });
397
395
 
398
396
  return function (_x4) {
399
397
  return _ref9.apply(this, arguments);
400
398
  };
401
399
  })());
402
- // eslint-disable-next-line no-console
403
- console.log('Watching for changes to %s...', parserName);
400
+ this._reporter.reportMessage('Watching for changes to ' + parserName + '...');
404
401
  });
405
402
 
406
403
  function watch(_x3) {
@@ -191,7 +191,7 @@ var SUBSCRIPTION_NAME = 'graphql-codegen';
191
191
  function updateFiles(files, baseDir, filter, fileChanges) {
192
192
  var fileMap = new Map();
193
193
  files.forEach(function (file) {
194
- fileMap.set(file.relPath, file);
194
+ file.exists && fileMap.set(file.relPath, file);
195
195
  });
196
196
 
197
197
  fileChanges.forEach(function (_ref2) {
@@ -199,15 +199,23 @@ function updateFiles(files, baseDir, filter, fileChanges) {
199
199
  exists = _ref2.exists,
200
200
  hash = _ref2['content.sha1hex'];
201
201
 
202
- var file = {
203
- relPath: name,
204
- hash: hash || hashFile(require('path').join(baseDir, name))
205
- };
206
- if (exists && filter(file)) {
207
- fileMap.set(name, file);
208
- } else {
209
- fileMap['delete'](name);
202
+ var shouldRemove = !exists;
203
+ if (!shouldRemove) {
204
+ var _file = {
205
+ exists: true,
206
+ relPath: name,
207
+ hash: hash || hashFile(require('path').join(baseDir, name))
208
+ };
209
+ if (filter(_file)) {
210
+ fileMap.set(name, _file);
211
+ } else {
212
+ shouldRemove = true;
213
+ }
210
214
  }
215
+ shouldRemove && fileMap.set(name, {
216
+ exists: false,
217
+ relPath: name
218
+ });
211
219
  });
212
220
  return new Set(fileMap.values());
213
221
  }
@@ -17,7 +17,9 @@ var _require = require('graphql'),
17
17
 
18
18
  function parseFile(baseDir, file) {
19
19
  var text = require('fs').readFileSync(require('path').join(baseDir, file.relPath), 'utf8');
20
- return parse(new Source(text, file.relPath));
20
+ return parse(new Source(text, file.relPath), {
21
+ experimentalFragmentVariables: true
22
+ });
21
23
  }
22
24
 
23
25
  exports.getParser = function getParser(baseDir) {
@@ -84,17 +84,18 @@ function find(text, filePath, _ref) {
84
84
  var cache = new (require('./RelayCompilerCache'))('FindGraphQLTags', 'v1');
85
85
 
86
86
  function memoizedFind(text, baseDir, file, options) {
87
+ !file.exists ? process.env.NODE_ENV !== 'production' ? invariant(false, 'FindGraphQLTags: Called with non-existent file `%s`', file.relPath) : invariant(false) : void 0;
87
88
  return cache.getOrCompute(file.hash + (options.validateNames ? '1' : '0'), function () {
88
89
  var absPath = require('path').join(baseDir, file.relPath);
89
90
  return find(text, absPath, options);
90
91
  });
91
92
  }
92
93
 
93
- var CREATE_CONTAINER_FUNCTIONS = {
94
- createFragmentContainer: true,
95
- createPaginationContainer: true,
96
- createRefetchContainer: true
97
- };
94
+ var CREATE_CONTAINER_FUNCTIONS = Object.create(null, {
95
+ createFragmentContainer: { value: true },
96
+ createPaginationContainer: { value: true },
97
+ createRefetchContainer: { value: true }
98
+ });
98
99
 
99
100
  var IGNORED_KEYS = {
100
101
  comments: true,
@@ -102,7 +102,7 @@ function flattenSelectionsInto(flattenedSelections, node, state, type) {
102
102
  flattenedSelections.set(nodeIdentifier, (0, _extends3['default'])({}, flattenedSelection, {
103
103
  selections: mergeSelections(flattenedSelection, selection, state, type)
104
104
  }));
105
- } else if (flattenedSelection.kind === 'FragmentSpread') {
105
+ } else if (flattenedSelection.kind === 'FragmentSpread' || flattenedSelection.kind === 'DeferrableFragmentSpread') {
106
106
  // Ignore duplicate fragment spreads.
107
107
  } else if (flattenedSelection.kind === 'LinkedField') {
108
108
  require('fbjs/lib/invariant')(selection.kind === 'LinkedField', 'FlattenTransform: Expected a LinkedField, got a %s', selection.kind);
@@ -20,21 +20,30 @@ var GraphQLConsoleReporter = function () {
20
20
  (0, _classCallCheck3['default'])(this, GraphQLConsoleReporter);
21
21
 
22
22
  this._verbose = options.verbose;
23
+ this._quiet = options.quiet;
23
24
  }
24
25
 
26
+ GraphQLConsoleReporter.prototype.reportMessage = function reportMessage(message) {
27
+ if (!this._quiet) {
28
+ process.stdout.write(message + '\n');
29
+ }
30
+ };
31
+
25
32
  GraphQLConsoleReporter.prototype.reportTime = function reportTime(name, ms) {
26
- if (this._verbose) {
33
+ if (this._verbose && !this.quiet) {
27
34
  var time = ms === 0 ? require('chalk').gray(' <1ms') : ms < 1000 ? require('chalk').blue(leftPad(5, ms + 'ms')) : require('chalk').red(Math.floor(ms / 10) / 100 + 's');
28
35
  process.stdout.write(' ' + time + ' ' + require('chalk').gray(name) + '\n');
29
36
  }
30
37
  };
31
38
 
32
39
  GraphQLConsoleReporter.prototype.reportError = function reportError(caughtLocation, error) {
33
- process.stdout.write(require('chalk').red('ERROR:\n' + error.message + '\n'));
34
- if (this._verbose) {
35
- var frames = error.stack.match(/^ {4}at .*$/gm);
36
- if (frames) {
37
- process.stdout.write(require('chalk').gray('From: ' + caughtLocation + '\n' + frames.join('\n') + '\n'));
40
+ if (!this._quiet) {
41
+ process.stdout.write(require('chalk').red('ERROR:\n' + error.message + '\n'));
42
+ if (this._verbose) {
43
+ var frames = error.stack.match(/^ {4}at .*$/gm);
44
+ if (frames) {
45
+ process.stdout.write(require('chalk').gray('From: ' + caughtLocation + '\n' + frames.join('\n') + '\n'));
46
+ }
38
47
  }
39
48
  }
40
49
  };
@@ -76,6 +76,8 @@ function printSelection(selection, indent, parentCondition) {
76
76
  str += parentCondition;
77
77
  str += printFragmentArguments(selection.args);
78
78
  str += printDirectives(selection.directives);
79
+ } else if (selection.kind === 'DeferrableFragmentSpread') {
80
+ str = selection.alias + ': ' + selection.storageKey;
79
81
  } else if (selection.kind === 'Condition') {
80
82
  var value = printValue(selection.condition);
81
83
  // For Flow
@@ -194,12 +194,20 @@ var Transformer = function () {
194
194
  nextNode = this._traverseChildren(prevNode, ['fields']);
195
195
  break;
196
196
  case 'Condition':
197
+ nextNode = this._traverseChildren(prevNode, ['directives', 'selections'], ['condition']);
198
+ if (!nextNode.selections.length) {
199
+ nextNode = null;
200
+ }
201
+ break;
197
202
  case 'InlineFragment':
198
203
  nextNode = this._traverseChildren(prevNode, ['directives', 'selections']);
199
204
  if (!nextNode.selections.length) {
200
205
  nextNode = null;
201
206
  }
202
207
  break;
208
+ case 'DeferrableFragmentSpread':
209
+ nextNode = this._traverseChildren(prevNode, ['args', 'fragmentArgs', 'directives']);
210
+ break;
203
211
  case 'Fragment':
204
212
  case 'Root':
205
213
  nextNode = this._traverseChildren(prevNode, ['argumentDefinitions', 'directives', 'selections']);
@@ -28,7 +28,7 @@ var NodeKeys = {
28
28
  RootArgumentDefinition: [],
29
29
  ScalarField: ['args', 'directives'],
30
30
  Variable: [],
31
- DeferrableFragmentSpread: ['args']
31
+ DeferrableFragmentSpread: ['args', 'directives', 'fragmentArgs']
32
32
  };
33
33
 
34
34
  function visitIR(root, visitor) {
@@ -26,6 +26,12 @@ var GraphQLMultiReporter = function () {
26
26
  this._reporters = reporters;
27
27
  }
28
28
 
29
+ GraphQLMultiReporter.prototype.reportMessage = function reportMessage(message) {
30
+ this._reporters.forEach(function (reporter) {
31
+ reporter.reportMessage(message);
32
+ });
33
+ };
34
+
29
35
  GraphQLMultiReporter.prototype.reportTime = function reportTime(name, ms) {
30
36
  this._reporters.forEach(function (reporter) {
31
37
  reporter.reportTime(name, ms);
@@ -24,7 +24,7 @@ var _require2 = require('./GraphQLSchemaUtils'),
24
24
  getNullableType = _require2.getNullableType,
25
25
  getRawType = _require2.getRawType,
26
26
  getTypeFromAST = _require2.getTypeFromAST,
27
- isOperationDefinitionAST = _require2.isOperationDefinitionAST;
27
+ isExecutableDefinitionAST = _require2.isExecutableDefinitionAST;
28
28
 
29
29
  var _require3 = require('graphql'),
30
30
  assertCompositeType = _require3.assertCompositeType,
@@ -75,7 +75,7 @@ var GraphQLParser = function () {
75
75
  // TODO T24511737 figure out if this is dangerous
76
76
  schema = extendSchema(schema, ast, { assumeValid: true });
77
77
  ast.definitions.forEach(function (definition) {
78
- if (isOperationDefinitionAST(definition)) {
78
+ if (isExecutableDefinitionAST(definition)) {
79
79
  nodes.push(_this.transform(schema, definition));
80
80
  }
81
81
  }, this);
@@ -132,7 +132,7 @@ function getInterfaces(type) {
132
132
  *
133
133
  * Determine if an AST node contains a fragment/operation definition.
134
134
  */
135
- function isOperationDefinitionAST(ast) {
135
+ function isExecutableDefinitionAST(ast) {
136
136
  return ast.kind === 'FragmentDefinition' || ast.kind === 'OperationDefinition';
137
137
  }
138
138
 
@@ -172,7 +172,7 @@ module.exports = {
172
172
  implementsInterface: implementsInterface,
173
173
  isAbstractType: isAbstractType,
174
174
  isUnionType: isUnionType,
175
- isOperationDefinitionAST: isOperationDefinitionAST,
175
+ isExecutableDefinitionAST: isExecutableDefinitionAST,
176
176
  isSchemaDefinitionAST: isSchemaDefinitionAST,
177
177
  mayImplement: mayImplement
178
178
  };
@@ -17,7 +17,6 @@ var _require = require('graphql'),
17
17
  KnownArgumentNamesRule = _require.KnownArgumentNamesRule,
18
18
  KnownTypeNamesRule = _require.KnownTypeNamesRule,
19
19
  LoneAnonymousOperationRule = _require.LoneAnonymousOperationRule,
20
- NoFragmentCyclesRule = _require.NoFragmentCyclesRule,
21
20
  NoUnusedVariablesRule = _require.NoUnusedVariablesRule,
22
21
  PossibleFragmentSpreadsRule = _require.PossibleFragmentSpreadsRule,
23
22
  ProvidedNonNullArgumentsRule = _require.ProvidedNonNullArgumentsRule,
@@ -51,8 +50,10 @@ module.exports = {
51
50
  GLOBAL_RULES: [KnownArgumentNamesRule,
52
51
  // TODO #19327202 Relay Classic generates some fragments in runtime, so Relay
53
52
  // Modern queries might reference fragments unknown in build time
54
- //KnownFragmentNamesRule,
55
- NoFragmentCyclesRule,
53
+ // KnownFragmentNamesRule,
54
+ // TODO: #25618795 Because of @argumentDefinitions, this validation
55
+ // incorrectly flags a subset of fragments using @include/@skip as recursive.
56
+ // NoFragmentCyclesRule,
56
57
  // TODO #19327144 Because of @argumentDefinitions, this validation
57
58
  // incorrectly marks some fragment variables as undefined.
58
59
  // NoUndefinedVariablesRule,
@@ -99,6 +99,20 @@ function transformFragmentSpread(context, fragments, scope, spread) {
99
99
  });
100
100
  }
101
101
 
102
+ function transformDeferrableFragmentSpread(context, fragments, scope, spread) {
103
+ var directives = transformDirectives(scope, spread.directives);
104
+ var fragment = context.getFragment(spread.name);
105
+ var appliedFragment = transformFragment(context, fragments, scope, fragment, spread.fragmentArgs);
106
+ if (!appliedFragment) {
107
+ return null;
108
+ }
109
+ return (0, _extends3['default'])({}, spread, {
110
+ fragmentArgs: [],
111
+ directives: directives,
112
+ name: appliedFragment.name
113
+ });
114
+ }
115
+
102
116
  function transformField(context, fragments, scope, field) {
103
117
  var args = transformArguments(scope, field.args);
104
118
  var directives = transformDirectives(scope, field.directives);
@@ -150,6 +164,8 @@ function transformSelections(context, fragments, scope, selections) {
150
164
  nextSelection = transformNode(context, fragments, scope, selection);
151
165
  } else if (selection.kind === 'FragmentSpread') {
152
166
  nextSelection = transformFragmentSpread(context, fragments, scope, selection);
167
+ } else if (selection.kind === 'DeferrableFragmentSpread') {
168
+ nextSelection = transformDeferrableFragmentSpread(context, fragments, scope, selection);
153
169
  } else if (selection.kind === 'Condition') {
154
170
  var conditionSelections = transformCondition(context, fragments, scope, selection);
155
171
  if (conditionSelections) {
@@ -43,13 +43,6 @@ function generate(node) {
43
43
  }
44
44
 
45
45
  var RelayCodeGenVisitor = {
46
- enter: function enter(node) {
47
- if ((node.kind === 'FragmentSpread' || node.kind === 'ScalarField') && node.metadata && node.metadata.deferred) {
48
- return deferrableFragmentSpread(node.metadata.deferredFragmentName, node.metadata.deferredArgumentName, node.metadata.deferredArgumentStorageKey, node.metadata.idType);
49
- }
50
- return node;
51
- },
52
-
53
46
  leave: {
54
47
  Batch: function Batch(node) {
55
48
  require('fbjs/lib/invariant')(node.requests.length !== 0, 'Batch must contain Requests.');
@@ -294,25 +287,4 @@ function getStaticStorageKey(field) {
294
287
  return getStorageKey(field, {});
295
288
  }
296
289
 
297
- function deferrableFragmentSpread(fragmentName, argumentName, storageKey, idType) {
298
- return {
299
- kind: 'DeferrableFragmentSpread',
300
- name: fragmentName,
301
- args: [{
302
- kind: 'Argument',
303
- name: argumentName,
304
- metadata: null,
305
- value: {
306
- kind: 'Variable',
307
- variableName: argumentName,
308
- metadata: null,
309
- type: idType
310
- },
311
- type: idType
312
- }],
313
- rootFieldVariable: argumentName,
314
- storageKey: storageKey
315
- };
316
- }
317
-
318
290
  module.exports = { generate: generate };
@@ -33,30 +33,55 @@ let run = (() => {
33
33
  if (options.watch && !hasWatchmanRootFile(srcDir)) {
34
34
  throw new Error(('\n--watch requires that the src directory have a valid watchman "root" file.\n\nRoot files can include:\n- A .git/ Git folder\n- A .hg/ Mercurial folder\n- A .watchmanconfig file\n\nEnsure that one such file exists in ' + srcDir + ' or its parents.\n ').trim());
35
35
  }
36
+ if (options.verbose && options.quiet) {
37
+ throw new Error("I can't be quiet and verbose at the same time");
38
+ }
36
39
 
37
- var reporter = new ConsoleReporter({ verbose: options.verbose });
40
+ var reporter = new ConsoleReporter({
41
+ verbose: options.verbose,
42
+ quiet: options.quiet
43
+ });
38
44
 
39
45
  var useWatchman = options.watchman && (yield WatchmanClient.isAvailable());
40
46
 
47
+ var schema = getSchema(schemaPath);
41
48
  var parserConfigs = {
42
- 'default': {
49
+ js: {
43
50
  baseDir: srcDir,
44
51
  getFileFilter: require('./RelayJSModuleParser').getFileFilter,
45
52
  getParser: require('./RelayJSModuleParser').getParser,
46
53
  getSchema: function getSchema() {
47
- return _getSchema(schemaPath);
54
+ return schema;
48
55
  },
49
56
  watchmanExpression: useWatchman ? buildWatchExpression(options) : null,
50
57
  filepaths: useWatchman ? null : getFilepathsFromGlob(srcDir, options)
58
+ },
59
+ graphql: {
60
+ baseDir: srcDir,
61
+ getParser: DotGraphQLParser.getParser,
62
+ getSchema: function getSchema() {
63
+ return schema;
64
+ },
65
+ watchmanExpression: useWatchman ? buildWatchExpression({
66
+ extensions: ['graphql'],
67
+ include: options.include,
68
+ exclude: options.exclude
69
+ }) : null,
70
+ filepaths: useWatchman ? null : getFilepathsFromGlob(srcDir, {
71
+ extensions: ['graphql'],
72
+ include: options.include,
73
+ exclude: options.exclude
74
+ })
51
75
  }
52
76
  };
53
77
  var writerConfigs = {
54
- 'default': {
78
+ js: {
55
79
  getWriter: getRelayFileWriter(srcDir),
56
80
  isGeneratedFile: function isGeneratedFile(filePath) {
57
81
  return filePath.endsWith('.js') && filePath.includes('__generated__');
58
82
  },
59
- parser: 'default'
83
+ parser: 'js',
84
+ baseParsers: ['graphql']
60
85
  }
61
86
  };
62
87
  var codegenRunner = new CodegenRunner({
@@ -93,7 +118,8 @@ require('babel-polyfill');
93
118
  var _require = require('./GraphQLCompilerPublic'),
94
119
  CodegenRunner = _require.CodegenRunner,
95
120
  ConsoleReporter = _require.ConsoleReporter,
96
- WatchmanClient = _require.WatchmanClient;
121
+ WatchmanClient = _require.WatchmanClient,
122
+ DotGraphQLParser = _require.DotGraphQLParser;
97
123
 
98
124
  var _require2 = require('graphql'),
99
125
  buildASTSchema = _require2.buildASTSchema,
@@ -130,8 +156,6 @@ function getFilepathsFromGlob(baseDir, options) {
130
156
  var glob = require('fast-glob');
131
157
  return glob.sync(patterns, {
132
158
  cwd: baseDir,
133
- bashNative: [],
134
- onlyFiles: true,
135
159
  ignore: exclude
136
160
  });
137
161
  }
@@ -170,7 +194,7 @@ function getRelayFileWriter(baseDir) {
170
194
  };
171
195
  }
172
196
 
173
- function _getSchema(schemaPath) {
197
+ function getSchema(schemaPath) {
174
198
  try {
175
199
  var source = require('fs').readFileSync(schemaPath, 'utf8');
176
200
  if (require('path').extname(schemaPath) === '.json') {
@@ -232,6 +256,10 @@ var argv = require('yargs').usage('Create Relay generated files\n\n' + '$0 --sch
232
256
  describe: 'More verbose logging',
233
257
  type: 'boolean'
234
258
  },
259
+ quiet: {
260
+ describe: 'No output to stdout',
261
+ type: 'boolean'
262
+ },
235
263
  watchman: {
236
264
  describe: 'Use watchman when not in watch mode',
237
265
  type: 'boolean',
@@ -23,7 +23,7 @@ var _require = require('graphql'),
23
23
  isInputType = _require.isInputType,
24
24
  GraphQLInterfaceType = _require.GraphQLInterfaceType,
25
25
  GraphQLList = _require.GraphQLList,
26
- GraphQLScalarType = _require.GraphQLScalarType;
26
+ GraphQLInputType = _require.GraphQLInputType;
27
27
 
28
28
  var _require2 = require('./GraphQLCompilerPublic'),
29
29
  IRTransformer = _require2.IRTransformer,
@@ -89,8 +89,6 @@ function transformOperations(context) {
89
89
  return context;
90
90
  }
91
91
 
92
- var idType = getIdType(context.clientSchema);
93
-
94
92
  // Next, transform any existing root operations to include references to
95
93
  // their dependent requests.
96
94
  var transformedContext = IRTransformer.transform(context, {
@@ -121,18 +119,8 @@ function transformOperations(context) {
121
119
  });
122
120
  return completeDeferrableOperation;
123
121
  });
124
- var transformedContextPostFragments = IRTransformer.transform(transformedContext, {
125
- FragmentSpread: function FragmentSpread(spread) {
126
- if (isDeferrable(spread)) {
127
- return (0, _extends3['default'])({}, spread, {
128
- metadata: (0, _extends3['default'])({}, spread.metadata, deferrableFragmentSpreadMetadata(spread.name, idType))
129
- });
130
- }
131
- return spread;
132
- }
133
- });
134
122
 
135
- return transformedContextPostFragments.addAll(deferrableOperations);
123
+ return transformedContext.addAll(deferrableOperations);
136
124
  }
137
125
 
138
126
  /**
@@ -364,16 +352,7 @@ function createDeferrableReference(context, spread) {
364
352
  metadata: null,
365
353
  typeCondition: nodeType,
366
354
  directives: [],
367
- selections: [{
368
- kind: 'ScalarField',
369
- name: 'id',
370
- alias: deferrableAlias(spread.name),
371
- args: [],
372
- handles: null,
373
- directives: spread.directives,
374
- metadata: (0, _extends3['default'])({}, spread.metadata, deferrableFragmentSpreadMetadata(spread.name, idType)),
375
- type: idType
376
- }]
355
+ selections: [deferrableFragmentSpread(spread, idType)]
377
356
  }]
378
357
  };
379
358
  }
@@ -427,7 +406,7 @@ function createDeferrableOperation(context, fragment) {
427
406
  kind: 'FragmentSpread',
428
407
  args: [],
429
408
  name: fragment.name,
430
- metadata: deferrableFragmentSpreadMetadata(fragment.name, idType),
409
+ metadata: null,
431
410
  directives: []
432
411
  }],
433
412
  type: nodeField.type
@@ -436,20 +415,34 @@ function createDeferrableOperation(context, fragment) {
436
415
  };
437
416
  }
438
417
 
439
- function deferrableFragmentSpreadMetadata(name, idType) {
440
- return {
441
- deferred: true,
442
- deferredFragmentName: name,
443
- deferredArgumentName: DEFERRABLE_ARGUMENT_NAME,
444
- deferredArgumentStorageKey: 'id',
445
- idType: idType
446
- };
447
- }
448
-
449
418
  function deferrableAlias(name) {
450
419
  return name + '_' + DEFERRABLE_ARGUMENT_NAME;
451
420
  }
452
421
 
422
+ function deferrableFragmentSpread(spread, idType) {
423
+ return {
424
+ kind: 'DeferrableFragmentSpread',
425
+ name: spread.name,
426
+ directives: [],
427
+ fragmentArgs: spread.args,
428
+ args: [{
429
+ kind: 'Argument',
430
+ name: DEFERRABLE_ARGUMENT_NAME,
431
+ metadata: null,
432
+ value: {
433
+ kind: 'Variable',
434
+ variableName: DEFERRABLE_ARGUMENT_NAME,
435
+ metadata: null,
436
+ type: idType
437
+ },
438
+ type: idType
439
+ }],
440
+ rootFieldVariable: DEFERRABLE_ARGUMENT_NAME,
441
+ storageKey: 'id',
442
+ alias: deferrableAlias(spread.name)
443
+ };
444
+ }
445
+
453
446
  function getNodeType(schema) {
454
447
  var nodeType = schema.getType('Node');
455
448
  require('fbjs/lib/invariant')(nodeType instanceof GraphQLInterfaceType, 'RelayDeferrableFragmentTransform: Schema must define the interface "Node".');
@@ -461,7 +454,7 @@ function getIdType(schema) {
461
454
  var idField = nodeType.getFields().id;
462
455
  require('fbjs/lib/invariant')(idField, 'RelayDeferrableFragmentTransform: "Node" must define the field "id"');
463
456
  var idType = getNamedType(idField.type);
464
- require('fbjs/lib/invariant')(idType instanceof GraphQLScalarType, 'RelayDeferrableFragmentTransform: "Node" must define the scalar field "id"');
457
+ require('fbjs/lib/invariant')(isInputType(idType), 'RelayDeferrableFragmentTransform: "Node" must define the scalar field "id"');
465
458
  return idType;
466
459
  }
467
460
 
@@ -31,7 +31,7 @@ var _require = require('./GraphQLCompilerPublic'),
31
31
  var _require2 = require('immutable'),
32
32
  ImmutableMap = _require2.Map;
33
33
 
34
- var isOperationDefinitionAST = SchemaUtils.isOperationDefinitionAST;
34
+ var isExecutableDefinitionAST = SchemaUtils.isExecutableDefinitionAST;
35
35
 
36
36
  var RelayFileWriter = function () {
37
37
  function RelayFileWriter(_ref) {
@@ -67,7 +67,7 @@ var RelayFileWriter = function () {
67
67
  var baseDefinitionNames = new Set();
68
68
  _this._baseDocuments.forEach(function (doc) {
69
69
  doc.definitions.forEach(function (def) {
70
- if (isOperationDefinitionAST(def) && def.name) {
70
+ if (isExecutableDefinitionAST(def) && def.name) {
71
71
  baseDefinitionNames.add(def.name.value);
72
72
  }
73
73
  });