UNPKG

make

Version:
345 lines (281 loc) 11.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); 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; }; }(); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _cli = require('./cli'); var _cli2 = _interopRequireDefault(_cli); var _stream = require('stream'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var exists = _fs2.default.existsSync; var assign = Object.assign; var Template = function (_CLI) { _inherits(Template, _CLI); _createClass(Template, [{ key: 'example', get: function get() { return 'make init <template> [options]'; } }, { key: 'home', get: function get() { return process.platform === 'win32' ? process.env.USERPROFILE : process.env.HOME; } }, { key: 'more', get: function get() { var _this2 = this; var lens = this.templates.map(function (template) { return template.name.length; }); var max = Math.max.apply(null, lens.concat(_cli2.default.PADDING)); var templates = this.templates.map(function (template) { var json = template.json; var config = json.make || {}; var desc = config.description || json.description || 'Generate ' + template.name + ' setup'; var deps = assign({}, json.dependencies, json.devDependencies); deps = Object.keys(deps).slice(0, 4).join(', '); deps = deps.length > _cli2.default.PADDING ? deps.slice(0, _cli2.default.PADDING) + '...' : deps; if (deps) deps = ' (' + deps + ')'; var pad = _this2.pad(template.name, max); var leftpad = _this2.options.leftpad || ' '; return '' + leftpad + template.name + pad + desc + deps; }).join('\n'); return '\n Templates:\n' + templates + '\n'; } // Used to parse arguments with minimist }, { key: 'alias', get: function get() { return { h: 'help', v: 'version', d: 'debug', f: 'force' }; } // Used to generate the help output }, { key: 'flags', get: function get() { return { help: 'Show this help output', version: 'Show package version', debug: 'Enable extended log output', force: 'Force file write even if already existing', skip: 'Skip scripts hook' }; } }, { key: 'directories', get: function get() { return [_path2.default.join(this.home, '.config/make/templates'), _path2.default.join(this.home, '.make/templates'), _path2.default.join(__dirname, '../templates')]; } }]); function Template() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; _classCallCheck(this, Template); var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Template).call(this, options)); _this.templates = _this.loadTemplates(); _this.names = _this.templates.map(function (dir) { return dir.name; }); return _this; } _createClass(Template, [{ key: 'init', value: function init() { var _this3 = this; if (this.argv.help) return this.help(); var args = this.parse(); var name = args._.shift(); return this.run(name, args._).then(function () { _this3.end(); }); } }, { key: 'expandTemplateDirectory', value: function expandTemplateDirectory(template) { var _this4 = this; var dir = template.dir; if (!exists(dir)) return template; var files = _fs2.default.readdirSync(dir).map(this.resolve(dir)).filter(this.file); var lengths = files.map(this.basename).map(function (file) { return file.length; }); var max = this.max = Math.max.apply(null, lengths) + 2; var cwd = _path2.default.resolve(); var promises = files.map(function (file) { var name = file.replace(dir + '/', ''); var dest = _path2.default.resolve(_path2.default.basename(file)); var destname = dest.replace(cwd, '.'); return _this4.template(file, dest).then(function () { _this4.info('%s%s-> %s', name, _this4.pad(name, max), destname); _this4.debug('Finished streaming %s content', _path2.default.basename(file)); }); }); return assign({}, template, { promises: promises }); } // template(file, dest = path.resolve(file)) { }, { key: 'template', value: function template(file) { var dest = arguments.length <= 1 || arguments[1] === undefined ? _path2.default.resolve(_path2.default.basename(file)) : arguments[1]; if (_path2.default.basename(file) === 'package.json') return this.json(file, dest); if (_path2.default.basename(file) === '.eslintrc') return this.json(file, dest); if (_path2.default.basename(file) === '.babelrc') return this.json(file, dest); return this.stream(file, dest); } }, { key: 'json', value: function json(file, dest) { var _this5 = this; if (exists(dest)) return this.mergeJSON(file, dest).then(function () { _this5.debug('Finished merging %s file', _path2.default.basename(file)); }); return this.stream(file, dest); } }, { key: 'mergeJSON', value: function mergeJSON(file, dest) { var _this6 = this; var name = _path2.default.basename(file); this.warning('%s%salready exists, merging', name, this.pad(name, this.max)); return new Promise(function (r, errback) { var data = _this6.readJSON(dest); var json = _this6.readJSON(file); var devs = json.devDependencies; var deps = json.dependencies; // make sure to ignore "make" field in JSON stringify var opts = { make: undefined }; if (devs) opts.devDependencies = assign({}, devs, data.devDependencies); if (deps) opts.dependencies = assign({}, deps, data.dependencies); var result = assign({}, json, data, opts); _this6.debug('JSON:', result); _fs2.default.writeFile(dest, JSON.stringify(result, null, 2), function (err) { return err ? errback(err) : r(); }); }); } }, { key: 'stream', value: function stream(file, dest) { var _this7 = this; return new Promise(function (r, errback) { var existing = exists(dest); var filename = _path2.default.basename(dest); var destname = dest.replace(_path2.default.resolve(), '.'); var output = existing ? _this7.noopStream() : _fs2.default.createWriteStream(dest); var input = _fs2.default.createReadStream(file); if (existing) _this7.warning('%s%salready exists, skipping', filename, _this7.pad(filename, _this7.max)); var stream = input.pipe(output).on('error', errback).on('close', r); }); } }, { key: 'run', value: function run() { var _this8 = this; var name = arguments.length <= 0 || arguments[0] === undefined ? 'default' : arguments[0]; var args = arguments[1]; var template = this.templates.find(function (template) { return template.name === name; }); if (!template) { return _cli2.default.fail('No "%s" template', name); } this.info('Running %s template in %s', name, args.join(' '), process.cwd()); this.config = template.json ? template.json.make || {} : {}; this.scripts = this.config.scripts || {}; return this.invoke('start').then(function () { var dir = _this8.expandTemplateDirectory(template); return Promise.all(dir.promises).then(_this8.invoke.bind(_this8, 'install')).catch(_cli2.default.fail); }); } }, { key: 'invoke', value: function invoke(name) { var args = this.args; if (this.argv.skip) return this.noop('Skipping %s script (--skip)', name); this.debug('Invoke %s', name, this.argv); return this.script('pre' + name).then(this.script.bind(this, name)).then(this.script.bind(this, 'post' + name)); } }, { key: 'noop', value: function noop() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } if (args.length) this.info.apply(this, args); return new Promise(function (r, errback) { r(); }); } }, { key: 'script', value: function script(name) { var scripts = this.scripts || {}; var script = scripts[name] || ''; if (!script) return this.noop(); this.info('%s script', name); return this.exec(script); } }, { key: 'loadTemplates', value: function loadTemplates() { var _this9 = this; var dirs = this.directories; this.debug('Load templates from %d directories', dirs.length); return dirs // Ignore invalid dirs .filter(this.exists) // Load template from these dirs .map(this.loadTemplatesFrom, this) // Flatten .reduce(function (a, b) { return a.concat(b); }, []) // Transfrom into a mapping { name: dir } .map(function (dir) { var json = _path2.default.join(dir, 'package.json'); return { dir: dir, name: _this9.basename(dir), json: exists(json) ? require(json) : {} }; }); } }, { key: 'loadTemplatesFrom', value: function loadTemplatesFrom(dir) { this.debug('Load templates from', dir); return _fs2.default.readdirSync(dir).map(this.resolve(dir), this).filter(this.directory); } }, { key: 'has', value: function has(name) { var names = arguments.length <= 1 || arguments[1] === undefined ? this.names : arguments[1]; return names.indexOf(name) !== -1; } }, { key: 'noopStream', value: function noopStream() { var stream = new _stream.Stream(); stream.write = function () {}; stream.end = function () { stream.emit('finish'); stream.emit('close'); }; return stream; } }]); return Template; }(_cli2.default); exports.default = Template; module.exports = exports['default'];