UNPKG

12 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _promise = require('babel-runtime/core-js/promise');
8
9var _promise2 = _interopRequireDefault(_promise);
10
11var _extends2 = require('babel-runtime/helpers/extends');
12
13var _extends3 = _interopRequireDefault(_extends2);
14
15var _assign = require('babel-runtime/core-js/object/assign');
16
17var _assign2 = _interopRequireDefault(_assign);
18
19var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
20
21var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
22
23var _from = require('babel-runtime/core-js/array/from');
24
25var _from2 = _interopRequireDefault(_from);
26
27var _keys = require('babel-runtime/core-js/object/keys');
28
29var _keys2 = _interopRequireDefault(_keys);
30
31var _set = require('babel-runtime/core-js/set');
32
33var _set2 = _interopRequireDefault(_set);
34
35var _child_process = require('child_process');
36
37var _child_process2 = _interopRequireDefault(_child_process);
38
39var _treeKill = require('tree-kill');
40
41var _treeKill2 = _interopRequireDefault(_treeKill);
42
43var _fastGlob = require('fast-glob');
44
45var _fastGlob2 = _interopRequireDefault(_fastGlob);
46
47var _path = require('path');
48
49var _path2 = _interopRequireDefault(_path);
50
51var _State = require('./State');
52
53var _State2 = _interopRequireDefault(_State);
54
55var _File = require('./File');
56
57var _File2 = _interopRequireDefault(_File);
58
59var _Rule = require('./Rule');
60
61var _Rule2 = _interopRequireDefault(_Rule);
62
63function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
64
65const VARIABLE_PATTERN = /\$\{?(\w+)\}?/g;
66
67class StateConsumer {
68
69 constructor(state, options) {
70 this.consumerOptions = {};
71
72 this.state = state;
73 this.options = new Proxy(options, {
74 get: (target, key) => {
75 return key in this.consumerOptions ? this.consumerOptions[key] : target[key];
76 },
77 set: (target, key, value) => {
78 this.setOption(this.consumerOptions, key, value);
79 return true;
80 },
81 ownKeys: target => {
82 const keys = new _set2.default((0, _keys2.default)(this.consumerOptions));
83
84 (0, _keys2.default)(target).forEach(key => keys.add(key));
85
86 return (0, _from2.default)(keys.values());
87 }
88 });
89 this.env = {
90 OUTDIR: this.options.outputDirectory || '.',
91 // $FlowIgnore
92 OUTEXT: `.${this.options.outputFormat}`,
93 JOB: this.options.jobName || this.state.env.NAME
94 };
95 }
96
97 addTarget(filePath) {
98 this.state.targets.add(filePath);
99 }
100
101 removeTarget(filePath) {
102 this.state.targets.delete(filePath);
103 }
104
105 addResolvedTarget(filePath) {
106 this.state.targets.add(this.resolvePath(filePath));
107 }
108
109 replaceResolvedTarget(oldFilePath, newFilePath) {
110 var _this = this;
111
112 return (0, _asyncToGenerator3.default)(function* () {
113 const x = _this.resolvePath(oldFilePath);
114 if (_this.state.targets.has(x)) {
115 yield _this.addResolvedTarget(newFilePath);
116 }
117 })();
118 }
119
120 addResolvedTargets(filePaths) {
121 for (const filePath of filePaths) {
122 this.addResolvedTarget(filePath);
123 }
124 }
125
126 get killToken() {
127 return this.state.killToken;
128 }
129
130 set killToken(value) {
131 this.state.killToken = value;
132 }
133
134 assignOptions(options) {
135 for (const name in options) {
136 const value = options[name];
137
138 if (name === 'jobs') {
139 let jobs = this.state.options.jobs;
140
141 if (!jobs) {
142 this.state.options.jobs = jobs = {};
143 }
144
145 for (const jobName in value) {
146 const subOptions = value[jobName];
147 let jobOptions = jobs[jobName];
148
149 if (!jobOptions) {
150 jobs[jobName] = jobOptions = {};
151 }
152
153 for (const jobOptionName in subOptions) {
154 this.setOption(jobOptions, jobOptionName, subOptions[jobOptionName]);
155 }
156 }
157 } else {
158 this.setOption(this.state.options, name, value);
159 }
160 }
161 }
162
163 setOption(store, name, value) {
164 const schema = this.state.optionSchema.get(name);
165 if (schema) {
166 let invalidType = false;
167
168 switch (schema.type) {
169 case 'string':
170 invalidType = typeof value !== 'string';
171 break;
172 case 'strings':
173 invalidType = !Array.isArray(value) || value.some(x => typeof x !== 'string');
174 break;
175 case 'number':
176 invalidType = typeof value !== 'number';
177 break;
178 case 'boolean':
179 invalidType = typeof value !== 'boolean';
180 break;
181 case 'variable':
182 invalidType = !(typeof value === 'string' || Array.isArray(value) && value.every(x => typeof x === 'string'));
183 break;
184 }
185
186 if (invalidType || schema.values && !schema.values.includes(value)) {
187 this.error(`Ignoring attempt to set \`${name}\` to a invalid value of \`${value.toString()}\``);
188 } else {
189 store[schema.name] = value;
190 }
191 } else if (name.startsWith('$')) {
192 // It's an environment variable
193 store[name] = value;
194 } else {
195 this.error(`Ignoring attempt to set unknown option \`${name}\` to a value of \`${value.toString()}\``);
196 }
197 }
198
199 checkForKill() {
200 if (this.state.killToken && this.state.killToken.error) throw this.state.killToken.error;
201 }
202
203 get ruleClasses() {
204 return this.state.ruleClasses;
205 }
206
207 get filePath() {
208 return this.state.filePath;
209 }
210
211 get rootPath() {
212 return this.state.rootPath;
213 }
214
215 get files() {
216 return this.state.files.values();
217 }
218
219 get rules() {
220 return this.state.rules.values();
221 }
222
223 get targets() {
224 const targets = new _set2.default();
225
226 for (const rule of this.rules) {
227 for (const file of rule.outputs) {
228 const ext = _path2.default.extname(file.filePath);
229 if (ext === `.${this.options.outputFormat}` || ext === '.xdv' && this.options.outputFormat === 'dvi') {
230 targets.add(file.filePath);
231 }
232 }
233 }
234
235 return (0, _from2.default)(targets.values());
236 }
237
238 getTargetPaths() {
239 return this.state.getTargetPaths();
240 }
241
242 getTargetFiles() {
243 return this.state.getTargetFiles();
244 }
245
246 addRule(rule) {
247 var _this2 = this;
248
249 return (0, _asyncToGenerator3.default)(function* () {
250 yield _this2.state.addRule(rule);
251 })();
252 }
253
254 normalizePath(filePath) {
255 return this.state.normalizePath(filePath);
256 }
257
258 resolvePath(filePath) {
259 return _path2.default.normalize(this.expandVariables(filePath));
260 }
261
262 expandVariables(value, additionalProperties = {}) {
263 const properties = (0, _assign2.default)({}, this.state.env, this.env, additionalProperties);
264
265 return value.replace(VARIABLE_PATTERN, (match, name) => properties[name] || match[0]);
266 }
267
268 globPath(pattern, { types = 'all', ignorePattern } = {}) {
269 var _this3 = this;
270
271 return (0, _asyncToGenerator3.default)(function* () {
272 try {
273 return yield (0, _fastGlob2.default)(_this3.expandVariables(pattern), {
274 cwd: _this3.rootPath,
275 bashNative: [],
276 onlyFiles: types === 'files',
277 onlyDirs: types === 'directories',
278 ignore: ignorePattern
279 });
280 } catch (error) {}
281
282 return [];
283 })();
284 }
285
286 getFile(filePath) {
287 var _this4 = this;
288
289 return (0, _asyncToGenerator3.default)(function* () {
290 const file = yield _this4.state.getFile(filePath);
291 if (file && _this4.options.jobName) file.jobNames.add(_this4.options.jobName);
292 return file;
293 })();
294 }
295
296 getFiles(filePaths) {
297 var _this5 = this;
298
299 return (0, _asyncToGenerator3.default)(function* () {
300 const files = [];
301 for (const filePath of filePaths) {
302 const file = yield _this5.getFile(filePath);
303 if (file) files.push(file);
304 }
305 return files;
306 })();
307 }
308
309 getGlobbedFiles(pattern) {
310 var _this6 = this;
311
312 return (0, _asyncToGenerator3.default)(function* () {
313 const files = [];
314 for (const filePath of yield _this6.globPath(pattern)) {
315 const file = yield _this6.getFile(filePath);
316 if (file) files.push(file);
317 }
318 return files;
319 })();
320 }
321
322 error(text, name = 'DiCy') {
323 this.log({ severity: 'error', name, text });
324 }
325
326 warning(text, name = 'DiCy') {
327 this.log({ severity: 'warning', name, text });
328 }
329
330 info(text, name = 'DiCy') {
331 this.log({ severity: 'info', name, text });
332 }
333
334 log(message) {
335 const severity = this.options.severity || 'warning';
336 if (severity === 'warning' && message.severity === 'info' || severity === 'error' && message.severity !== 'error') return;
337 this.emit('log', (0, _extends3.default)({ type: 'log' }, message));
338 }
339
340 get components() {
341 return this.state.components;
342 }
343
344 addNode(x) {
345 this.state.addNode(x);
346 }
347
348 removeNode(x) {
349 this.state.addNode(x);
350 }
351
352 hasEdge(x, y) {
353 return this.state.hasEdge(x, y);
354 }
355
356 addEdge(x, y) {
357 this.state.addEdge(x, y);
358 }
359
360 removeEdge(x, y) {
361 this.state.removeEdge(x, y);
362 }
363
364 isGrandparentOf(x, y) {
365 return this.state.isGrandparentOf(x, y);
366 }
367
368 getResolvedFile(filePath) {
369 var _this7 = this;
370
371 return (0, _asyncToGenerator3.default)(function* () {
372 return _this7.getFile(_this7.resolvePath(filePath));
373 })();
374 }
375
376 // EventEmmitter proxy
377 addListener(eventName, listener) {
378 return this.state.addListener(eventName, listener);
379 }
380
381 emit(eventName, ...args) {
382 return this.state.emit(eventName, ...args);
383 }
384
385 eventNames() {
386 return this.state.eventNames();
387 }
388
389 getMaxListeners() {
390 return this.state.eventNames();
391 }
392
393 listenerCount(eventName) {
394 return this.state.listenerCount(eventName);
395 }
396
397 listeners(eventName) {
398 return this.state.listeners(eventName);
399 }
400
401 on(eventName, listener) {
402 return this.state.on(eventName, listener);
403 }
404
405 once(eventName, listener) {
406 return this.state.once(eventName, listener);
407 }
408
409 prependListener(eventName, listener) {
410 return this.state.prependListener(eventName, listener);
411 }
412
413 prependOnceListener(eventName, listener) {
414 return this.state.prependOnceListener(eventName, listener);
415 }
416
417 removeAllListeners(eventName) {
418 return this.state.removeAllListeners(eventName);
419 }
420
421 removeListener(eventName, listener) {
422 return this.state.removeListener(eventName, listener);
423 }
424
425 setMaxListeners(n) {
426 return this.state.setMaxListeners(n);
427 }
428
429 executeChildProcess(command, options) {
430 return new _promise2.default((resolve, reject) => {
431 let stdout;
432 let stderr;
433 let exited = false;
434 const handleExit = error => {
435 if (exited) return;
436 exited = true;
437
438 if (child.pid) this.state.processes.delete(child.pid);
439 if (error) {
440 reject(error);
441 } else {
442 resolve({ stdout, stderr });
443 }
444 };
445 const child = _child_process2.default.spawn(command, options);
446
447 if (child.pid) this.state.processes.add(child.pid);
448 child.on('error', handleExit);
449 child.on('close', (code, signal) => {
450 let error;
451 if (code !== 0 || signal !== null) {
452 error = new Error(`Command failed: \`${command}\`\n${stderr || ''}`.trim());
453 // $FlowIgnore
454 error.code = code;
455 // $FlowIgnore
456 error.signal = signal;
457 }
458 handleExit(error);
459 });
460 if (child.stdout) {
461 child.stdout.setEncoding('utf8');
462 child.stdout.on('data', data => {
463 stdout = `${stdout || ''}${data}`;
464 });
465 }
466 if (child.stderr) {
467 child.stderr.setEncoding('utf8');
468 child.stderr.on('data', data => {
469 stderr = `${stderr || ''}${data}`;
470 });
471 }
472 });
473 }
474
475 killChildProcesses() {
476 for (const pid of this.state.processes.values()) {
477 (0, _treeKill2.default)(pid);
478 }
479 this.state.processes.clear();
480 }
481
482 isOutputOf(file, ruleId) {
483 return this.state.isOutputOf(file, ruleId);
484 }
485}
486exports.default = StateConsumer;
\No newline at end of file