generator-runner.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. 'use strict';
  2. var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard");
  3. var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
  4. var _Object$defineProperty2 = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
  5. _Object$defineProperty2(exports, "__esModule", {
  6. value: true
  7. });
  8. exports.default = _default;
  9. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/define-property"));
  10. var _defineProperties = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/define-properties"));
  11. var _getOwnPropertyDescriptors = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors"));
  12. var _getOwnPropertyDescriptor = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor"));
  13. var _getOwnPropertySymbols = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols"));
  14. var _reduce = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/reduce"));
  15. var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify"));
  16. var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));
  17. var _forEach = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/for-each"));
  18. var _keys = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/keys"));
  19. var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter"));
  20. var _defineProperty3 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
  21. var _entries = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/entries"));
  22. var _assign = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/assign"));
  23. var _promptBypass = _interopRequireDefault(require("./prompt-bypass"));
  24. var buildInActions = _interopRequireWildcard(require("./actions"));
  25. function ownKeys(object, enumerableOnly) { var keys = (0, _keys.default)(object); if (_getOwnPropertySymbols.default) { var symbols = (0, _getOwnPropertySymbols.default)(object); if (enumerableOnly) symbols = (0, _filter.default)(symbols).call(symbols, function (sym) { return (0, _getOwnPropertyDescriptor.default)(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
  26. function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { var _context3; (0, _forEach.default)(_context3 = ownKeys(source, true)).call(_context3, function (key) { (0, _defineProperty3.default)(target, key, source[key]); }); } else if (_getOwnPropertyDescriptors.default) { (0, _defineProperties.default)(target, (0, _getOwnPropertyDescriptors.default)(source)); } else { var _context4; (0, _forEach.default)(_context4 = ownKeys(source)).call(_context4, function (key) { (0, _defineProperty2.default)(target, key, (0, _getOwnPropertyDescriptor.default)(source, key)); }); } } return target; }
  27. function _default(plopfileApi, flags) {
  28. let abort; // triggers inquirer with the correct prompts for this generator
  29. // returns a promise that resolves with the user's answers
  30. const runGeneratorPrompts = async function (genObject, bypassArr = []) {
  31. const {
  32. prompts
  33. } = genObject;
  34. if (prompts == null) {
  35. throw Error(`${genObject.name} has no prompts`);
  36. }
  37. if (typeof prompts === 'function') {
  38. return await prompts(plopfileApi.inquirer);
  39. } // handle bypass data when provided
  40. const [promptsAfterBypass, bypassAnswers] = (0, _promptBypass.default)(prompts, bypassArr, plopfileApi);
  41. return await plopfileApi.inquirer.prompt(promptsAfterBypass).then(answers => (0, _assign.default)(answers, bypassAnswers));
  42. }; // Run the actions for this generator
  43. const runGeneratorActions = async function (genObject, data = {}, hooks = {}) {
  44. const noop = () => {};
  45. const {
  46. onSuccess = noop,
  47. // runs after each successful action
  48. onFailure = noop,
  49. // runs after each failed action
  50. onComment = noop // runs for each comment line in the actions array
  51. } = hooks;
  52. const changes = []; // array of changed made by the actions
  53. const failures = []; // array of actions that failed
  54. let {
  55. actions
  56. } = genObject; // the list of actions to execute
  57. const customActionTypes = getCustomActionTypes();
  58. const actionTypes = (0, _assign.default)({}, customActionTypes, buildInActions);
  59. abort = false; // if action is a function, run it to get our array of actions
  60. if (typeof actions === 'function') {
  61. actions = actions(data);
  62. } // if actions are not defined... we cannot proceed.
  63. if (actions == null) {
  64. throw Error(`${genObject.name} has no actions`);
  65. } // if actions are not an array, invalid!
  66. if (!(actions instanceof Array)) {
  67. throw Error(`${genObject.name} has invalid actions`);
  68. }
  69. for (let [actionIdx, action] of (0, _entries.default)(actions).call(actions)) {
  70. // including strings in the actions array is used for commenting
  71. if (typeof action === 'string' && abort) {
  72. continue;
  73. }
  74. if (typeof action === 'string') {
  75. onComment(action);
  76. continue;
  77. }
  78. const actionIsFunction = typeof action === 'function';
  79. const actionCfg = actionIsFunction ? {
  80. type: 'function'
  81. } : action;
  82. const actionLogic = actionIsFunction ? action : actionTypes[actionCfg.type]; // bail out if a previous action aborted
  83. if (abort) {
  84. const failure = {
  85. type: actionCfg.type || '',
  86. path: actionCfg.path || '',
  87. error: 'Aborted due to previous action failure'
  88. };
  89. onFailure(failure);
  90. failures.push(failure);
  91. continue;
  92. }
  93. actionCfg.force = flags.force === true || actionCfg.force === true;
  94. if (typeof actionLogic !== 'function') {
  95. if (actionCfg.abortOnFail !== false) {
  96. abort = true;
  97. }
  98. const failure = {
  99. type: actionCfg.type || '',
  100. path: actionCfg.path || '',
  101. error: `Invalid action (#${actionIdx + 1})`
  102. };
  103. onFailure(failure);
  104. failures.push(failure);
  105. continue;
  106. }
  107. try {
  108. const actionResult = await executeActionLogic(actionLogic, actionCfg, data);
  109. onSuccess(actionResult);
  110. changes.push(actionResult);
  111. } catch (failure) {
  112. if (actionCfg.abortOnFail !== false) {
  113. abort = true;
  114. }
  115. onFailure(failure);
  116. failures.push(failure);
  117. }
  118. }
  119. return {
  120. changes,
  121. failures
  122. };
  123. }; // handle action logic
  124. const executeActionLogic = async function (action, cfg, data) {
  125. var _context;
  126. const type = cfg.type || '';
  127. let cfgData = cfg.data || {}; // data can also be a function that returns a data object
  128. if (typeof cfgData === 'function') {
  129. cfgData = await cfgData();
  130. } // check if action should run
  131. if (typeof cfg.skip === 'function') {
  132. // Merge main data and config data in new object
  133. const reasonToSkip = await cfg.skip(_objectSpread({}, data, {}, cfgData));
  134. if (typeof reasonToSkip === 'string') {
  135. // Return actionResult instead of string
  136. return {
  137. type: 'skip',
  138. path: reasonToSkip
  139. };
  140. }
  141. } // track keys that can be applied to the main data scope
  142. const cfgDataKeys = (0, _filter.default)(_context = (0, _keys.default)(cfgData)).call(_context, k => typeof data[k] === 'undefined'); // copy config data into main data scope so it's available for templates
  143. (0, _forEach.default)(cfgDataKeys).call(cfgDataKeys, k => {
  144. data[k] = cfgData[k];
  145. });
  146. return await _promise.default.resolve(action(data, cfg, plopfileApi)).then( // show the resolved value in the console
  147. result => ({
  148. type,
  149. path: typeof result === 'string' ? result : (0, _stringify.default)(result)
  150. }), // a rejected promise is treated as a failure
  151. err => {
  152. throw {
  153. type,
  154. path: '',
  155. error: err.message || err.toString()
  156. };
  157. }) // cleanup main data scope so config data doesn't leak
  158. .finally(() => (0, _forEach.default)(cfgDataKeys).call(cfgDataKeys, k => {
  159. delete data[k];
  160. }));
  161. }; // request the list of custom actions from the plopfile
  162. function getCustomActionTypes() {
  163. var _context2;
  164. return (0, _reduce.default)(_context2 = plopfileApi.getActionTypeList()).call(_context2, function (types, name) {
  165. types[name] = plopfileApi.getActionType(name);
  166. return types;
  167. }, {});
  168. }
  169. return {
  170. runGeneratorActions,
  171. runGeneratorPrompts
  172. };
  173. }