UNPKG

15.2 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 *
8 * @format
9 */
10'use strict';
11
12var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator");
13
14var _toConsumableArray2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/toConsumableArray"));
15
16var CodegenRunner =
17/*#__PURE__*/
18function () {
19 // parser => writers that are affected by it
20 function CodegenRunner(options) {
21 var _this = this;
22
23 this.parsers = {};
24 this.parserConfigs = options.parserConfigs;
25 this.writerConfigs = options.writerConfigs;
26 this.onlyValidate = options.onlyValidate;
27 this.onComplete = options.onComplete;
28 this._reporter = options.reporter;
29 this._sourceControl = options.sourceControl;
30 this.parserWriters = {};
31
32 for (var _parser in options.parserConfigs) {
33 this.parserWriters[_parser] = new Set();
34 }
35
36 var _loop = function _loop(_writer) {
37 var config = options.writerConfigs[_writer];
38 config.baseParsers && config.baseParsers.forEach(function (parser) {
39 return _this.parserWriters[parser].add(_writer);
40 });
41
42 _this.parserWriters[config.parser].add(_writer);
43 };
44
45 for (var _writer in options.writerConfigs) {
46 _loop(_writer);
47 }
48 }
49
50 var _proto = CodegenRunner.prototype;
51
52 _proto.compileAll =
53 /*#__PURE__*/
54 function () {
55 var _compileAll = _asyncToGenerator(function* () {
56 // reset the parsers
57 this.parsers = {};
58
59 for (var parserName in this.parserConfigs) {
60 try {
61 yield this.parseEverything(parserName);
62 } catch (e) {
63 this._reporter.reportError('CodegenRunner.compileAll', e);
64
65 return 'ERROR';
66 }
67 }
68
69 var hasChanges = false;
70
71 for (var writerName in this.writerConfigs) {
72 var result = yield this.write(writerName);
73
74 if (result === 'ERROR') {
75 return 'ERROR';
76 }
77
78 if (result === 'HAS_CHANGES') {
79 hasChanges = true;
80 }
81 }
82
83 return hasChanges ? 'HAS_CHANGES' : 'NO_CHANGES';
84 });
85
86 return function compileAll() {
87 return _compileAll.apply(this, arguments);
88 };
89 }();
90
91 _proto.compile =
92 /*#__PURE__*/
93 function () {
94 var _compile = _asyncToGenerator(function* (writerName) {
95 var _this2 = this;
96
97 var writerConfig = this.writerConfigs[writerName];
98 var parsers = [writerConfig.parser];
99
100 if (writerConfig.baseParsers) {
101 writerConfig.baseParsers.forEach(function (parser) {
102 return parsers.push(parser);
103 });
104 } // Don't bother resetting the parsers
105
106
107 yield require("./GraphQLCompilerProfiler").asyncContext('CodegenRunner:parseEverything', function () {
108 return Promise.all(parsers.map(function (parser) {
109 return _this2.parseEverything(parser);
110 }));
111 });
112 return yield this.write(writerName);
113 });
114
115 return function compile(_x) {
116 return _compile.apply(this, arguments);
117 };
118 }();
119
120 _proto.getDirtyWriters = function getDirtyWriters(filePaths) {
121 var _this3 = this;
122
123 return require("./GraphQLCompilerProfiler").asyncContext('CodegenRunner:getDirtyWriters',
124 /*#__PURE__*/
125 _asyncToGenerator(function* () {
126 var dirtyWriters = new Set(); // Check if any files are in the output
127
128 for (var configName in _this3.writerConfigs) {
129 var config = _this3.writerConfigs[configName];
130 var _iteratorNormalCompletion = true;
131 var _didIteratorError = false;
132 var _iteratorError = undefined;
133
134 try {
135 for (var _iterator = filePaths[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
136 var _filePath = _step.value;
137
138 if (config.isGeneratedFile(_filePath)) {
139 dirtyWriters.add(configName);
140 }
141 }
142 } catch (err) {
143 _didIteratorError = true;
144 _iteratorError = err;
145 } finally {
146 try {
147 if (!_iteratorNormalCompletion && _iterator["return"] != null) {
148 _iterator["return"]();
149 }
150 } finally {
151 if (_didIteratorError) {
152 throw _iteratorError;
153 }
154 }
155 }
156 } // Check for files in the input
157
158
159 yield Promise.all(Object.keys(_this3.parserConfigs).map(function (parserConfigName) {
160 return require("./GraphQLCompilerProfiler").waitFor('Watchman:query',
161 /*#__PURE__*/
162 _asyncToGenerator(function* () {
163 var client = new (require("./GraphQLWatchmanClient"))();
164 var config = _this3.parserConfigs[parserConfigName];
165 var dirs = yield client.watchProject(config.baseDir);
166 var relativeFilePaths = filePaths.map(function (filePath) {
167 return require("path").relative(config.baseDir, filePath);
168 });
169 var query = {
170 expression: ['allof', config.watchmanExpression, ['name', relativeFilePaths, 'wholename']],
171 fields: ['exists'],
172 relative_root: dirs.relativePath
173 };
174 var result = yield client.command('query', dirs.root, query);
175 client.end();
176
177 if (result.files.length > 0) {
178 _this3.parserWriters[parserConfigName].forEach(function (writerName) {
179 return dirtyWriters.add(writerName);
180 });
181 }
182 }));
183 }));
184 return dirtyWriters;
185 }));
186 };
187
188 _proto.parseEverything =
189 /*#__PURE__*/
190 function () {
191 var _parseEverything = _asyncToGenerator(function* (parserName) {
192 if (this.parsers[parserName]) {
193 // no need to parse
194 return;
195 }
196
197 var parserConfig = this.parserConfigs[parserName];
198 this.parsers[parserName] = parserConfig.getParser(parserConfig.baseDir);
199 var filter = parserConfig.getFileFilter ? parserConfig.getFileFilter(parserConfig.baseDir) : anyFileFilter;
200
201 if (parserConfig.filepaths && parserConfig.watchmanExpression) {
202 throw new Error('Provide either `watchmanExpression` or `filepaths` but not both.');
203 }
204
205 var files;
206
207 if (parserConfig.watchmanExpression) {
208 files = yield require("./CodegenWatcher").queryFiles(parserConfig.baseDir, parserConfig.watchmanExpression, filter);
209 } else if (parserConfig.filepaths) {
210 files = yield require("./CodegenWatcher").queryFilepaths(parserConfig.baseDir, parserConfig.filepaths, filter);
211 } else {
212 throw new Error('Either `watchmanExpression` or `filepaths` is required to query files');
213 }
214
215 this.parseFileChanges(parserName, files);
216 });
217
218 return function parseEverything(_x2) {
219 return _parseEverything.apply(this, arguments);
220 };
221 }();
222
223 _proto.parseFileChanges = function parseFileChanges(parserName, files) {
224 var _this4 = this;
225
226 return require("./GraphQLCompilerProfiler").run('CodegenRunner.parseFileChanges', function () {
227 var parser = _this4.parsers[parserName]; // this maybe should be await parser.parseFiles(files);
228
229 parser.parseFiles(files);
230 });
231 }; // We cannot do incremental writes right now.
232 // When we can, this could be writeChanges(writerName, parserName, parsedDefinitions)
233
234
235 _proto.write = function write(writerName) {
236 var _this5 = this;
237
238 return require("./GraphQLCompilerProfiler").asyncContext('CodegenRunner.write',
239 /*#__PURE__*/
240 _asyncToGenerator(function* () {
241 try {
242 _this5._reporter.reportMessage("\nWriting ".concat(writerName));
243
244 var _this5$writerConfigs$ = _this5.writerConfigs[writerName],
245 writeFiles = _this5$writerConfigs$.writeFiles,
246 _parser2 = _this5$writerConfigs$.parser,
247 baseParsers = _this5$writerConfigs$.baseParsers,
248 isGeneratedFile = _this5$writerConfigs$.isGeneratedFile;
249
250 var baseDocuments = require("immutable").Map();
251
252 if (baseParsers) {
253 baseParsers.forEach(function (baseParserName) {
254 baseDocuments = baseDocuments.merge(_this5.parsers[baseParserName].documents());
255 });
256 }
257
258 var _this5$parserConfigs$ = _this5.parserConfigs[_parser2],
259 _baseDir = _this5$parserConfigs$.baseDir,
260 generatedDirectoriesWatchmanExpression = _this5$parserConfigs$.generatedDirectoriesWatchmanExpression;
261 var generatedDirectories = [];
262
263 if (generatedDirectoriesWatchmanExpression) {
264 var relativePaths = yield require("./CodegenWatcher").queryDirectories(_baseDir, generatedDirectoriesWatchmanExpression);
265 generatedDirectories = relativePaths.map(function (x) {
266 return require("path").join(_baseDir, x);
267 });
268 } // always create a new writer: we have to write everything anyways
269
270
271 var documents = _this5.parsers[_parser2].documents();
272
273 var schema = require("./GraphQLCompilerProfiler").run('getSchema', function () {
274 return _this5.parserConfigs[_parser2].getSchema();
275 });
276
277 var outputDirectories = yield writeFiles({
278 onlyValidate: _this5.onlyValidate,
279 schema: schema,
280 documents: documents,
281 baseDocuments: baseDocuments,
282 generatedDirectories: generatedDirectories,
283 sourceControl: _this5._sourceControl,
284 reporter: _this5._reporter
285 });
286 var _iteratorNormalCompletion2 = true;
287 var _didIteratorError2 = false;
288 var _iteratorError2 = undefined;
289
290 try {
291 for (var _iterator2 = outputDirectories.values()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
292 var dir = _step2.value;
293 var all = (0, _toConsumableArray2["default"])(dir.changes.created).concat((0, _toConsumableArray2["default"])(dir.changes.updated), (0, _toConsumableArray2["default"])(dir.changes.deleted), (0, _toConsumableArray2["default"])(dir.changes.unchanged));
294 var _iteratorNormalCompletion3 = true;
295 var _didIteratorError3 = false;
296 var _iteratorError3 = undefined;
297
298 try {
299 for (var _iterator3 = all[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
300 var filename = _step3.value;
301
302 var _filePath2 = dir.getPath(filename);
303
304 !isGeneratedFile(_filePath2) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'CodegenRunner: %s returned false for isGeneratedFile, ' + 'but was in generated directory', _filePath2) : require("fbjs/lib/invariant")(false) : void 0;
305 }
306 } catch (err) {
307 _didIteratorError3 = true;
308 _iteratorError3 = err;
309 } finally {
310 try {
311 if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
312 _iterator3["return"]();
313 }
314 } finally {
315 if (_didIteratorError3) {
316 throw _iteratorError3;
317 }
318 }
319 }
320 }
321 } catch (err) {
322 _didIteratorError2 = true;
323 _iteratorError2 = err;
324 } finally {
325 try {
326 if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
327 _iterator2["return"]();
328 }
329 } finally {
330 if (_didIteratorError2) {
331 throw _iteratorError2;
332 }
333 }
334 }
335
336 var onCompleteCallback = _this5.onComplete;
337
338 if (onCompleteCallback != null) {
339 onCompleteCallback(Array.from(outputDirectories.values()));
340 }
341
342 var combinedChanges = require("./CodegenDirectory").combineChanges(Array.from(outputDirectories.values()));
343
344 require("./CodegenDirectory").printChanges(combinedChanges, {
345 onlyValidate: _this5.onlyValidate
346 });
347
348 return require("./CodegenDirectory").hasChanges(combinedChanges) ? 'HAS_CHANGES' : 'NO_CHANGES';
349 } catch (e) {
350 _this5._reporter.reportError('CodegenRunner.write', e);
351
352 return 'ERROR';
353 }
354 }));
355 };
356
357 _proto.watchAll =
358 /*#__PURE__*/
359 function () {
360 var _watchAll = _asyncToGenerator(function* () {
361 // get everything set up for watching
362 yield this.compileAll();
363
364 for (var parserName in this.parserConfigs) {
365 yield this.watch(parserName);
366 }
367 });
368
369 return function watchAll() {
370 return _watchAll.apply(this, arguments);
371 };
372 }();
373
374 _proto.watch =
375 /*#__PURE__*/
376 function () {
377 var _watch = _asyncToGenerator(function* (parserName) {
378 var _this6 = this;
379
380 var parserConfig = this.parserConfigs[parserName];
381
382 if (!parserConfig.watchmanExpression) {
383 throw new Error('`watchmanExpression` is required to watch files');
384 } // watchCompile starts with a full set of files as the changes
385 // But as we need to set everything up due to potential parser dependencies,
386 // we should prevent the first watch callback from doing anything.
387
388
389 var firstChange = true;
390 yield require("./CodegenWatcher").watchCompile(parserConfig.baseDir, parserConfig.watchmanExpression, parserConfig.getFileFilter ? parserConfig.getFileFilter(parserConfig.baseDir) : anyFileFilter,
391 /*#__PURE__*/
392 function () {
393 var _ref4 = _asyncToGenerator(function* (files) {
394 !_this6.parsers[parserName] ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'Trying to watch an uncompiled parser config: %s', parserName) : require("fbjs/lib/invariant")(false) : void 0;
395
396 if (firstChange) {
397 firstChange = false;
398 return;
399 }
400
401 var dependentWriters = [];
402
403 _this6.parserWriters[parserName].forEach(function (writer) {
404 return dependentWriters.push(writer);
405 });
406
407 try {
408 if (!_this6.parsers[parserName]) {
409 // have to load the parser and make sure all of its dependents are set
410 yield _this6.parseEverything(parserName);
411 } else {
412 _this6.parseFileChanges(parserName, files);
413 }
414
415 yield Promise.all(dependentWriters.map(function (writer) {
416 return _this6.write(writer);
417 }));
418 } catch (error) {
419 _this6._reporter.reportError('CodegenRunner.watch', error);
420 }
421
422 _this6._reporter.reportMessage("Watching for changes to ".concat(parserName, "..."));
423 });
424
425 return function (_x4) {
426 return _ref4.apply(this, arguments);
427 };
428 }());
429
430 this._reporter.reportMessage("Watching for changes to ".concat(parserName, "..."));
431 });
432
433 return function watch(_x3) {
434 return _watch.apply(this, arguments);
435 };
436 }();
437
438 return CodegenRunner;
439}();
440
441function anyFileFilter(file) {
442 return true;
443}
444
445module.exports = CodegenRunner;
\No newline at end of file