Skip to content

Commit

Permalink
feat: add egg-init args
Browse files Browse the repository at this point in the history
  • Loading branch information
czy88840616 committed Nov 1, 2019
1 parent 634b748 commit d6c3582
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 124 deletions.
3 changes: 2 additions & 1 deletion packages/midway-init/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"extends": "eslint-config-egg",
"rules": {
"no-console": "off",
"no-else-return": "off"
"no-else-return": "off",
"no-empty-function": "off"
}
}
126 changes: 90 additions & 36 deletions packages/midway-init/lib/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { LightGenerator } = require('light-generator');
const { Input, Select, Form } = require('enquirer');
const chalk = require('chalk');
const { getParser } = require('./parser');
const { EventEmitter } = require('events');

async function sleep(timeout) {
return new Promise(resolve => {
Expand All @@ -18,10 +19,29 @@ const defaultOptions = {
templateListPath: path.join(__dirname, '../boilerplate.json'),
};

class MidwayInitCommand {
class MidwayInitCommand extends EventEmitter {

constructor(npmClient) {
super();
this.npmClient = npmClient || 'npm';
this._innerPrompt = null;
this.showPrompt = true;
}

set prompt(value) {
const originRun = value.run;
value.run = async () => {
await this.beforePromptSubmit();
return await originRun.call(value);
};
this._innerPrompt = value;
}

get prompt() {
return this._innerPrompt;
}

async beforePromptSubmit() {
}

async run(cwd, args) {
Expand All @@ -30,10 +50,30 @@ class MidwayInitCommand {

this.templateList = await this.getTemplateList();

if (argv.template) {
if (argv.dir) {
// support --dir argument
this.targetPath = argv.dir;
}

if (argv.type) {
// support --type argument
this.templateName = argv.type;
await this.createFromTemplate();
} else if (argv.template) {
// support --template argument
// ready targetDir
await this.createTargetDir();
const lightGenerator = new LightGenerator();
const generator = lightGenerator.defineLocalPath({
templatePath: this.getAbsoluteDir(argv.template),
targetPath: this.targetPath,
});
await this.execBoilerplate(generator);
} else if (argv.package) {
// support --package argument
await this.createFromTemplate(argv.package);
} else {
const prompt = new Select({
this.prompt = new Select({
name: 'templateName',
message: 'Hello, traveller.\n Which template do you like?',
choices: Object.keys(this.templateList).map(template => {
Expand All @@ -43,40 +83,64 @@ class MidwayInitCommand {
result: value => {
return value.split(' - ')[0];
},
show: this.showPrompt,
});
// get user input template
this.template = await prompt.run();
this.templateName = await this.prompt.run();
await this.createFromTemplate();
}
// done
this.printUsage();
}

async createFromTemplate() {
if (!this.argv.dir) {
const prompt = new Input({
async createFromTemplate(packageName) {
// ready targetDir
await this.createTargetDir();
const lightGenerator = new LightGenerator();
const generator = lightGenerator.defineNpmPackage({
npmClient: this.npmClient,
npmPackage: packageName || this.templateList[this.templateName].package,
targetPath: this.targetPath,
});
await this.execBoilerplate(generator);
}

async getTemplateList() {
if (!this.templateName) {
return require(defaultOptions.templateListPath);
}
}

async readyGenerate() {
console.log();
await sleep(1000);
console.log('1...');
await sleep(1000);
console.log('2...');
await sleep(1000);
console.log('3...');
await sleep(1000);
console.log('Enjoy it...');
}

async createTargetDir() {
if (!this.targetPath) {
this.prompt = new Input({
message: 'The directory where the boilerplate should be created',
initial: 'my_midway_app',
show: this.showPrompt,
});
// get target path where template will be copy to
this.targetPath = await prompt.run();
} else {
this.targetPath = this.argv.dir;
this.targetPath = await this.prompt.run();
}
this.targetPath = this.getAbsoluteDir(this.targetPath);
}

const boilerplatePath = this.targetPath || '';
const newPath = path.join(process.cwd(), boilerplatePath);
const lightGenerator = new LightGenerator();
const generator = lightGenerator.defineNpmPackage({
npmClient: this.npmClient,
npmPackage: this.templateList[this.template].package,
targetPath: newPath,
});

async execBoilerplate(generator) {
const args = await generator.getParameterList();
const argsKeys = Object.keys(args);
if (argsKeys && argsKeys.length) {
const prompt = new Form({
this.prompt = new Form({
name: 'user',
message: 'Please provide the following information:',
choices: argsKeys.map(argsKey => {
Expand All @@ -86,9 +150,10 @@ class MidwayInitCommand {
initial: `${args[argsKey].default}`,
};
}),
show: this.showPrompt,
});

const parameters = await prompt.run();
const parameters = await this.prompt.run();
await this.readyGenerate();
await generator.run(parameters);
} else {
Expand All @@ -97,22 +162,11 @@ class MidwayInitCommand {
}
}

async getTemplateList() {
if (!this.template) {
return require(defaultOptions.templateListPath);
getAbsoluteDir(dir) {
if (!path.isAbsolute(dir)) {
dir = path.join(process.cwd(), dir);
}
}

async readyGenerate() {
console.log();
await sleep(1000);
console.log('1...');
await sleep(1000);
console.log('2...');
await sleep(1000);
console.log('3...');
await sleep(1000);
console.log('Enjoy it...');
return dir;
}

printUsage() {
Expand Down
13 changes: 4 additions & 9 deletions packages/midway-init/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,17 @@
"version": "1.12.1",
"dependencies": {
"chalk": "^2.4.2",
"enquirer": "^2.3.0",
"light-generator": "^1.3.1",
"enquirer": "^2.3.2",
"light-generator": "^1.3.3",
"yargs": "^11.1.0"
},
"main": "lib/command.js",
"devDependencies": {
"coffee": "^5.2.1",
"eslint": "^6.1.0",
"eslint-config-egg": "^7.0.0",
"intelli-espower-loader": "^1.0.1",
"midway-bin": "^1.12.1",
"mm": "^2.5.0",
"mz-modules": "^2.1.0",
"power-assert": "^1.6.1",
"proxy": "^0.2.4",
"rimraf": "^3.0.0"
"power-assert": "^1.6.1"
},
"keywords": [
"midway",
Expand All @@ -31,7 +26,7 @@
"files": [
"bin",
"lib",
"boilerplate"
"boilerplate.json"
],
"scripts": {
"lint": "eslint bin lib test",
Expand Down
90 changes: 32 additions & 58 deletions packages/midway-init/test/helper.js
Original file line number Diff line number Diff line change
@@ -1,67 +1,41 @@
'use strict';

module.exports = class Helper {
constructor(command) {
this.command = command;
this.inquirer = command.inquirer;
this.originPrompt = this.inquirer.prompt;
this.KEY_UP = '\u001b[A';
this.KEY_DOWN = '\u001b[B';
this.KEY_LEFT = '\u001b[D';
this.KEY_RIGHT = '\u001b[C';
this.KEY_ENTER = '\n';
this.KEY_SPACE = ' ';
const Command = require('../lib/command');

class TestCommand extends Command {

constructor() {
super();
this.showPrompt = false;
}

mockPrompt(arr) {
this.promptAction = arr;
}

/**
* send keys after `inquirer.prompt` trigger
*
* @param {Array} actions - each item will be sent after once call, if item is array, then send sub item after a tick
*
* @example
* mock([ helper.KEY_DOWN + helper.KEY_DOWN, [ 'test', 'this is xxx', 'TZ' ]]);
*/
mock(actions) {
this.inquirer.prompt = opts => {
const result = this.originPrompt.call(this.inquirer, opts);
const key = actions.shift() || '\n';
if (key) {
if (Array.isArray(opts) && !Array.isArray(key)) {
throw new Error(`prompt multiple question, but mock with only one key \`${key}\`, should provide array`);
} else {
this.sendKey(key);
async beforePromptSubmit() {
this.prompt.once('run', async () => {
const value = this.promptAction.shift();
if (value) {
for (const flag of value) {
if (Array.isArray(flag)) {
await this.prompt.keypress.apply(this.prompt, flag);
} else if (typeof flag === 'string') {
try {
for (const key of flag.split('')) {
await this.prompt.keypress(key);
}
} catch (err) {
console.error(err);
}
}
}
}
return result;
};
}

/**
* restore prompt to origin fn
*/
restore() {
this.inquirer.prompt = this.originPrompt;
await this.prompt.submit();
this.prompt.close();
});
}
}

/**
* send key to process.stdin
*
* @param {String/Array} arr - key list, send one by one after a tick
* @return {Promise} after all sent
*/
sendKey(arr) {
if (Array.isArray(arr)) {
return arr.reduce((promise, key) => {
return promise.then(() => this.sendKey(key));
}, Promise.resolve());
} else {
const key = arr;
return new Promise(resolve => {
setTimeout(() => {
process.stdin.emit('data', key + '\n');
resolve(key);
}, 10);
});
}
}
};
exports.TestCommand = TestCommand;
Loading

0 comments on commit d6c3582

Please sign in to comment.