UNPKG

11.2 kBJavaScriptView Raw
1'use strict';
2
3var _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
5function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
7var scrolex = require('scrolex');
8var globby = require('globby');
9var debug = require('depurar')('invig');
10var applyEachSeries = require('async/applyEachSeries');
11var queue = require('async/queue');
12var waterfall = require('async/waterfall');
13var path = require('path');
14var fs = require('fs');
15var pkgUp = require('pkg-up');
16
17var 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 // const invigRootRel = path.relative(process.cwd(), invigRoot)
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 // 'commonjs',
127 // 'exponent',
128 'multi-var'];
129 var unsafe = ['let', 'class', 'template', 'default-param',
130 // 'includes'
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 // let relative
184 if (stat && stat.isFile()) {
185 // File
186 var resolve = path.resolve(this.opts.src);
187 files = [resolve];
188 } else if (stat && stat.isDirectory()) {
189 // Directory
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 // Pattern
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 // Assume this was a JS snippet on STDIN already
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
283module.exports = Invig;
284//# sourceMappingURL=Invig.js.map
\No newline at end of file