1 | 'use strict';
|
2 |
|
3 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
4 |
|
5 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
6 |
|
7 | var scrolex = require('scrolex');
|
8 | var globby = require('globby');
|
9 | var debug = require('depurar')('invig');
|
10 | var applyEachSeries = require('async/applyEachSeries');
|
11 | var queue = require('async/queue');
|
12 | var waterfall = require('async/waterfall');
|
13 | var path = require('path');
|
14 | var fs = require('fs');
|
15 | var pkgUp = require('pkg-up');
|
16 |
|
17 | var Invig = function () {
|
18 | function Invig() {
|
19 | var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
20 |
|
21 | _classCallCheck(this, Invig);
|
22 |
|
23 | this.opts = opts;
|
24 | }
|
25 |
|
26 | _createClass(Invig, [{
|
27 | key: 'initProject',
|
28 | value: function initProject(files, cb) {
|
29 | var projectPackage = require(this._projectPackagePath);
|
30 | var projectRoot = path.dirname(this._projectPackagePath);
|
31 | var projectRootRel = path.relative(process.cwd(), projectRoot) || '.';
|
32 | var invigRoot = __dirname + '/..';
|
33 |
|
34 | var invigPackage = require(invigRoot + '/package.json');
|
35 | var npmInstallNeeded = [];
|
36 |
|
37 | scrolex.stick('Adding npm task project config', { components: 'invig>' + projectRootRel });
|
38 | if (this.opts.dryrun === false) {
|
39 | if (!projectPackage.scripts) {
|
40 | projectPackage.scripts = {};
|
41 | }
|
42 | if (!projectPackage.scripts.lint) {
|
43 | projectPackage.scripts.lint = 'eslint .';
|
44 | }
|
45 | if (!projectPackage.scripts.fix) {
|
46 | projectPackage.scripts.fix = 'eslint . --fix';
|
47 | }
|
48 | if (!projectPackage.scripts.build) {
|
49 | projectPackage.scripts.build = 'babel src --source-maps --out-dir lib';
|
50 | if (!projectPackage.scripts['build:watch']) {
|
51 | projectPackage.scripts['build:watch'] = 'babel src --watch --source-maps --out-dir lib';
|
52 | }
|
53 | }
|
54 | }
|
55 |
|
56 | scrolex.stick('Adding dependencies task project config', { components: 'invig>' + projectRootRel });
|
57 | if (this.opts.dryrun === false) {
|
58 | if (!projectPackage.dependencies) {
|
59 | projectPackage.dependencies = {};
|
60 | }
|
61 | if (!projectPackage.devDependencies) {
|
62 | projectPackage.devDependencies = {};
|
63 | }
|
64 |
|
65 | for (var name in invigPackage.dependencies) {
|
66 | if (name.match(/^(babel|eslint|es6-promise)/)) {
|
67 | if (projectPackage.devDependencies[name] !== invigPackage.dependencies[name]) {
|
68 | projectPackage.devDependencies[name] = invigPackage.dependencies[name];
|
69 | npmInstallNeeded.push('Add ' + name + ' to devDependencies');
|
70 | }
|
71 | }
|
72 | }
|
73 |
|
74 | var removeDeps = ['coffee-script', 'coffeelint'];
|
75 | removeDeps.forEach(function (name) {
|
76 | if (projectPackage.dependencies[name]) {
|
77 | delete projectPackage.dependencies[name];
|
78 | npmInstallNeeded.push('Remove ' + name + ' from dependencies');
|
79 | }
|
80 | if (projectPackage.devDependencies[name]) {
|
81 | delete projectPackage.devDependencies[name];
|
82 | npmInstallNeeded.push('Remove ' + name + ' from devDependencies');
|
83 | }
|
84 | });
|
85 | }
|
86 |
|
87 | scrolex.stick('Writing eslint project config', { components: 'invig>' + projectRootRel });
|
88 | if (this.opts.dryrun === false) {
|
89 | this.copySyncNoOverwrite(invigRoot + '/.eslintrc', projectRoot + '/.eslintrc');
|
90 | }
|
91 |
|
92 | scrolex.stick('Writing babel project config', { components: 'invig>' + projectRootRel });
|
93 | if (this.opts.dryrun === false) {
|
94 | this.copySyncNoOverwrite(invigRoot + '/.babelrc', projectRoot + '/.babelrc');
|
95 | }
|
96 |
|
97 | scrolex.stick('Writing eslint ignores', { components: 'invig>' + projectRootRel });
|
98 | if (this.opts.dryrun === false) {
|
99 | this.copySyncNoOverwrite(invigRoot + '/.eslintignore', projectRoot + '/.eslintignore');
|
100 | }
|
101 |
|
102 | scrolex.stick('Writing back project config ', { components: 'invig>' + projectRootRel });
|
103 | fs.writeFileSync(this._projectPackagePath, JSON.stringify(projectPackage, null, 2), 'utf-8');
|
104 |
|
105 | if (npmInstallNeeded.length > 0) {
|
106 | scrolex.stick('Running npm install to accomodate these changes: ' + npmInstallNeeded.join('. '), { components: 'invig>' + projectRootRel });
|
107 | var cmd = 'yarn || npm install';
|
108 | scrolex.exe(cmd, { cwd: this._projectDir, components: 'invig>' + projectRootRel }, function (err) {
|
109 | return cb(err, files);
|
110 | });
|
111 | } else {
|
112 | return cb(null, files);
|
113 | }
|
114 | }
|
115 | }, {
|
116 | key: 'toJs',
|
117 | value: function toJs(srcPath, cb) {
|
118 | var cmd = this.opts.npmBinDir + '/decaffeinate --loose-includes --loose-for-of --allow-invalid-constructors --keep-commonjs --prefer-const --loose-default-params ' + srcPath + ' && rm -f ' + srcPath;
|
119 | scrolex.exe(cmd, { cwd: this._projectDir, components: 'invig>' + path.relative(process.cwd(), srcPath) }, cb);
|
120 | }
|
121 | }, {
|
122 | key: 'toEs6',
|
123 | value: function toEs6(srcPath, cb) {
|
124 | srcPath = srcPath.replace(/\.coffee$/, '.js');
|
125 | var safe = ['arrow', 'for-of', 'for-each', 'arg-rest', 'arg-spread', 'obj-method', 'obj-shorthand', 'no-strict',
|
126 |
|
127 |
|
128 | 'multi-var'];
|
129 | var unsafe = ['let', 'class', 'template', 'default-param',
|
130 |
|
131 | 'destruct-param'];
|
132 |
|
133 | var list = [].concat(safe, unsafe).join(',');
|
134 |
|
135 | var moveCommandWin = 'move /y ' + srcPath.replace(/\//g, '\\') + '.es6 ' + srcPath.replace(/\//g, '\\');
|
136 | var moveCommandOthers = 'mv -f ' + srcPath + '.es6 ' + srcPath;
|
137 | var moveCommand = /^win/.test(process.platform) ? moveCommandWin : moveCommandOthers;
|
138 |
|
139 | var cmd = this.opts.npmBinDir + '/lebab --transform=' + list + ' ' + srcPath + ' --out-file ' + srcPath + '.es6 && ' + moveCommand;
|
140 |
|
141 | scrolex.exe(cmd, { cwd: this._projectDir, components: 'invig>' + path.relative(process.cwd(), srcPath) }, cb);
|
142 | }
|
143 | }, {
|
144 | key: 'toPrettier',
|
145 | value: function toPrettier(srcPath, cb) {
|
146 | srcPath = srcPath.replace(/\.coffee$/, '.js');
|
147 | var cmd = this.opts.npmBinDir + '/prettier --single-quote --print-width 180 --write ' + srcPath;
|
148 | scrolex.exe(cmd, { cwd: this._projectDir, components: 'invig>' + path.relative(process.cwd(), srcPath) }, cb);
|
149 | }
|
150 | }, {
|
151 | key: 'toEslintStandard',
|
152 | value: function toEslintStandard(srcPath, cb) {
|
153 | srcPath = srcPath.replace(/\.coffee$/, '.js');
|
154 | var cmd = this.opts.npmBinDir + '/eslint --config ' + this._projectDir + '/.eslintrc --fix ' + srcPath;
|
155 | scrolex.exe(cmd, { cwd: this._projectDir, components: 'invig>' + path.relative(process.cwd(), srcPath) }, cb);
|
156 | }
|
157 | }, {
|
158 | key: 'convertFile',
|
159 | value: function convertFile(srcPath, cb) {
|
160 | var fns = [];
|
161 | var extension = path.extname(srcPath).toLowerCase();
|
162 |
|
163 | if (extension === '.coffee') {
|
164 | fns.push(this.toJs.bind(this));
|
165 | }
|
166 | fns.push(this.toEs6.bind(this));
|
167 | fns.push(this.toPrettier.bind(this));
|
168 | fns.push(this.toEslintStandard.bind(this));
|
169 |
|
170 | applyEachSeries(fns, srcPath, cb);
|
171 | }
|
172 | }, {
|
173 | key: 'findFiles',
|
174 | value: function findFiles(cb) {
|
175 | var files = [];
|
176 | var stat = {};
|
177 | try {
|
178 | stat = fs.lstatSync(this.opts.src);
|
179 | } catch (e) {
|
180 | stat = false;
|
181 | }
|
182 |
|
183 |
|
184 | if (stat && stat.isFile()) {
|
185 |
|
186 | var resolve = path.resolve(this.opts.src);
|
187 | files = [resolve];
|
188 | } else if (stat && stat.isDirectory()) {
|
189 |
|
190 | var _resolve = path.resolve(this.opts.src);
|
191 | files = globby.sync([_resolve + '/**/*.coffee', _resolve + '/**/*.es5', _resolve + '/**/*.es6', _resolve + '/**/*.js', '!' + _resolve + '/node_modules/**']);
|
192 | } else {
|
193 |
|
194 | files = globby.sync(this.opts.src);
|
195 | }
|
196 | if (!files || files.length === 0) {
|
197 | return cb(new Error('Source argument: "' + this.opts.src + '" returned no input files to work on.'));
|
198 | }
|
199 |
|
200 | return cb(null, files);
|
201 | }
|
202 | }, {
|
203 | key: 'copySyncNoOverwrite',
|
204 | value: function copySyncNoOverwrite(src, dst) {
|
205 | if (!fs.existsSync(dst)) {
|
206 | fs.writeFileSync(dst, fs.readFileSync(src, 'utf-8'), 'utf-8');
|
207 | }
|
208 | }
|
209 | }, {
|
210 | key: 'findProject',
|
211 | value: function findProject(files, cb) {
|
212 | this._projectPackagePath = pkgUp.sync(path.dirname(files[0]));
|
213 |
|
214 | if (!this._projectPackagePath) {
|
215 | return cb(new Error('No package.json found, unable to establish project root. '));
|
216 | }
|
217 |
|
218 | this._projectDir = path.dirname(this._projectPackagePath);
|
219 | return cb(null, files);
|
220 | }
|
221 | }, {
|
222 | key: 'processFiles',
|
223 | value: function processFiles(files, cb) {
|
224 | var q = queue(this.convertFile.bind(this), this.opts.concurrency);
|
225 | q.push(files);
|
226 | q.drain = function () {
|
227 | return cb(null, files);
|
228 | };
|
229 | }
|
230 | }, {
|
231 | key: 'upgradeDeps',
|
232 | value: function upgradeDeps(files, cb) {
|
233 | if (this.opts.check) {
|
234 | scrolex.exe(this.opts.npmBinDir + '/npm-check ' + this._projectDir, { cwd: this._projectDir, components: 'invig>' + path.relative(process.cwd(), this._projectDir) }, function (err, stdout) {
|
235 | if (err) {
|
236 | return cb(err);
|
237 | }
|
238 | return cb(null);
|
239 | });
|
240 | } else {
|
241 | return cb(null);
|
242 | }
|
243 | }
|
244 | }, {
|
245 | key: 'runOnStdIn',
|
246 | value: function runOnStdIn(stdin, cb) {
|
247 | var _this = this;
|
248 |
|
249 | this._projectDir = __dirname + '/..';
|
250 | var coffeePath = __dirname + '/tmpFile.coffee';
|
251 | var jsPath = __dirname + '/tmpFile.js';
|
252 |
|
253 | fs.writeFileSync('' + coffeePath, stdin, 'utf-8');
|
254 | scrolex.persistOpts({ mode: 'silent' });
|
255 |
|
256 | this.toJs(coffeePath, function (err) {
|
257 | if (err) {
|
258 |
|
259 | fs.writeFileSync('' + jsPath, fs.readFileSync('' + coffeePath, 'utf-8'), 'utf-8');
|
260 | }
|
261 | _this.convertFile(jsPath, function (err) {
|
262 | debug(err);
|
263 | process.stdout.write(fs.readFileSync('' + jsPath, 'utf-8'));
|
264 | try {
|
265 | fs.unlinkSync('' + jsPath);
|
266 | fs.unlinkSync('' + coffeePath);
|
267 | } catch (e) {}
|
268 |
|
269 | return cb(null);
|
270 | });
|
271 | });
|
272 | }
|
273 | }, {
|
274 | key: 'runOnPattern',
|
275 | value: function runOnPattern(cb) {
|
276 | waterfall([this.findFiles.bind(this), this.findProject.bind(this), this.initProject.bind(this), this.processFiles.bind(this), this.upgradeDeps.bind(this)], cb);
|
277 | }
|
278 | }]);
|
279 |
|
280 | return Invig;
|
281 | }();
|
282 |
|
283 | module.exports = Invig;
|
284 |
|
\ | No newline at end of file |