UNPKG

node-plop

Version:

programmatic plopping for fun and profit

221 lines (187 loc) 6.28 kB
'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var co = require('co'); var path = require('path'); var colors = require('colors'); var fspp = require('./fs-promise-proxy'); module.exports = function (plop) { var abort, basePath; // if not already an absolute path, make an absolute path from the basePath (plopfile location) var makePath = function makePath(p) { return path.isAbsolute(p) ? p : path.join(basePath, p); }; // triggers inquirer with the correct prompts for this generator // returns a promise that resolves with the user's answers var runGeneratorPrompts = co.wrap(function* (genObject) { if (genObject.prompts == null) { throw Error(genObject.name + ' does no have prompts.'); } return yield plop.inquirer.prompt(genObject.prompts); }); // Run the actions for this generator var runGeneratorActions = co.wrap(function* (genObject, data) { var changes = []; // array of changed made by the actions var failures = []; // array of actions that failed var actions = genObject.actions; // the list of actions to execute basePath = genObject.basePath; // the path that contains this generator's plopfile abort = false; // if action is a function, run it to get our array of actions if (typeof actions === 'function') { actions = actions(data); } // if actions are not defined... we cannot proceed. if (actions == null) { throw Error(genObject.name + ' does no have actions.'); } // if actions are not an array, invalid! if (!(actions instanceof Array)) { throw Error(genObject.name + ' does has invalid actions.'); } var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = actions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var action = _step.value; // bail out if a previous action aborted if (abort) { failures.push({ type: action.type || '', path: action.path || '', error: 'Aborted due to previous action failure' }); continue; } var actionInterfaceTest = testActionInterface(action); if (actionInterfaceTest !== true) { failures.push(actionInterfaceTest); continue; } try { var result = void 0; if (typeof action === 'function') { result = yield executeCustomAction(action, data); } else { result = yield executeAction(action, data); } changes.push(result); } catch (failure) { failures.push(failure); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return { changes: changes, failures: failures }; }); ///// // action handlers // // custom action functions var executeCustomAction = co.wrap(function* (action, data) { var failure = makeErrorLogger(action.type || 'function', '', action.abortOnFail); // convert any returned data into a promise to // return and wait on return yield Promise.resolve(action(data)).then( // show the resolved value in the console function (result) { return { type: action.type || 'function', path: colors.blue(result.toString()) }; }, // a rejected promise is treated as a failure function (err) { throw failure(err.message || err.toString()); }); }); // basic function objects var executeAction = co.wrap(function* (action, data) { var template = action.template; var filePath = makePath(plop.renderString(action.path || '', data)); var failure = makeErrorLogger(action.type, filePath, action.abortOnFail); try { if (action.templateFile) { template = yield fspp.readFile(makePath(action.templateFile)); } if (template == null) { template = ''; } // check path var pathExists = yield fspp.fileExists(filePath); // handle type if (action.type === 'add') { if (pathExists) { throw failure('File already exists: ' + filePath); } else { yield fspp.makeDir(path.dirname(filePath)); yield fspp.writeFile(filePath, plop.renderString(template, data)); } } else if (action.type === 'modify') { if (!pathExists) { throw failure('File does not exists: ' + filePath); } else { var fileData = yield fspp.readFile(filePath); fileData = fileData.replace(action.pattern, plop.renderString(template, data)); yield fspp.writeFile(filePath, fileData); } } else { throw failure('Invalid action type: ' + action.type); } return { type: action.type, path: filePath }; } catch (err) { throw failure(JSON.stringify(err)); } }); function testActionInterface(action) { // action functions are valid, end of story if (typeof action === 'function') { return true; } // it's not even an object, you fail! if ((typeof action === 'undefined' ? 'undefined' : _typeof(action)) !== 'object') { return { type: '', path: '', error: 'Invalid action object: ' + JSON.stringify(action) }; } var type = action.type, path = action.path, template = action.template, templateFile = action.templateFile, pattern = action.pattern, abortOnFail = action.abortOnFail; var failure = makeErrorLogger(type, path, abortOnFail); var validActionTypes = ['add', 'modify']; if (!validActionTypes.includes(type)) { return failure('Invalid action type "' + type + '"'); } if (typeof path !== 'string' || path.length === 0) { return failure('Invalid path "' + path + '"'); } return true; } function makeErrorLogger(type, path, abortOnFail) { return function (error) { if (abortOnFail !== false) { abort = true; } return { type: type, path: path, error: error }; }; } return { runGeneratorActions: runGeneratorActions, runGeneratorPrompts: runGeneratorPrompts }; };