update omi-cli

This commit is contained in:
pasturn 2017-04-09 00:15:44 +08:00
parent 4bd73a30a1
commit 2b4933a00b
13 changed files with 585 additions and 117 deletions

View File

@ -3,26 +3,43 @@
CLI for scaffolding Omi.js projects.
### Installation
## Installation
Prerequisites: Node.js (>=6.x), npm version 3+
```
$ npm install omi-cli -g
```
### Usage
## Usage
initialize a new omi application `omi-app` :
```
$ omi init // in current directory
$ omi init [project name] // in new directroy named project name
$ omi init [project name] [cn] // shift to cnpm mirror
```
Example:
initialize a new omi project `omi-pr` :
```
$ omi init-pr // in current directory
$ omi init-pr [project name] // in new directroy named project name
```
if you want to compile project for ssr, you can run:
```
$ omi pr
```
in your omi-pr project
## Example:
```
$ omi init app
$ omi init-pr project
$ omi pr
.....
```
omi-cli will run npm to install dependencies.
omi-cli will run npm command to install dependencies automatically. You could switch the mirror source with:
```
$ omi init app -m cnpm
```
we support to shift from default to `npm`, `cnpm` or `taobao` mirror.
## Scaffolding

View File

@ -8,51 +8,93 @@ var chalk = require('chalk');
var exists = require('fs-exists-sync');
var spawn = require('cross-spawn');
var options = {
cmd: '',
projectName: '',
mirror: 'default',
language: 'en'
}
program
.version(require('../package').version, '-v, --version')
.usage('init [project-name]')
.on('--help', help);
.usage('<cmd> [project-name]')
.option('-m, --mirror <mirror>', 'Select mirror like: npm, cnpm, taobao', /^(npm|cnpm|taobao|nj|rednpm|skimdb)$/i)
.option('-l, --language <language>', 'Select language: en / cn', selectLanguage)
.on('-h, --help', help);
program
.command('init [projectName]')
.description('Initialize a new Omi application in the current folder')
.action(function(projectName, option){
var cmd = 'init';
if(option.parent.mirror){
options.mirror = option.parent.mirror;
}
switchCommand(cmd, {project: projectName, mirror: options.mirror, language: options.language})
})
program
.command('init-pr [projectName]')
.description('Initialize a new Omi-Pr in the current folder')
.action(function(projectName, option){
var cmd = 'init-pr';
if(option.parent.mirror){
options.mirror = option.parent.mirror;
}
switchCommand(cmd, {project: projectName, mirror: options.mirror, language: options.language})
})
program
.command('pr')
.description('Compile your omi project')
.action(function(option){
var cmd = 'pr';
switchCommand(cmd, {language: options.language})
})
program
.command('*')
.action(function(){
spawn('omi', ['-h'], { stdio: 'inherit'})
})
program.parse(process.argv);
var args = process.argv.slice(3);
let cmdstr = program.args[0];
if (cmdstr) {
const binFile = executable(cmdstr);
if (binFile) {
console.log();
console.log(chalk.bold.cyan("Omi-cli") + " is initializing... ");
secede(spawn('node', [].concat([binFile], args), {stdio: 'inherit'}))
function switchCommand (cmd, args) {
if (cmd) {
require('../lib/' + cmd)(args);
} else {
program.help();
setTimeout(program.help, 0);
}
} else {
program.help();
}
function isCnFuc(language){
return language === "cn" ? true : false
}
function selectLanguage(language){
if(language !== 'en' && language !== 'cn'){
language = 'en';
}
options.language = language;
return language;
}
function executable(cmd) {
var file = join(__dirname, 'omi-' + cmd);
return exists(file) ? file : void 0;
}
function help() {
console.log(' Commands:');
console.log();
console.log(` ${chalk.green('init [project-name]')} Initialize a new Omi application in the current folder `);
console.log();
console.log(` ${chalk.green('init [project-name] [cn]')} Shift the npm registry to cnpm mirror `);
console.log(` ${chalk.green('init-pr [project-name]')} Initialize a new Omi-Pr in the current folder `)
console.log(` ${chalk.green('pr')} Compile your omi project `)
console.log();
console.log(' All commands can be run with -h (or --help) for more information.')
}
function executable(cmdstr) {
const file = join(__dirname, 'omi-' + cmdstr);
if (exists(file)) {
return file
}
}
function secede(line){
line.on('close', function(code){
process.exit(code)
})
}

View File

@ -1,9 +0,0 @@
#!/usr/bin/env node
var program = require('commander');
program
.arguments('[project-name]')
.parse(process.argv);
require('../lib/init')(program);

107
cli/lib/init-pr.js Normal file
View File

@ -0,0 +1,107 @@
var path = require('path');
var join = path.join;
var basename = path.basename;
var vfs = require('vinyl-fs');
// var renameSync = require('fs').renameSync;
var existsSync = require('fs').existsSync;
var chalk = require('chalk');
var through = require('through2');
var emptyDir = require('empty-dir');
var logger = require('./logger');
var info = logger.info;
var error = logger.error;
var success = logger.success;
var isCnFun = require('./utils').isCnFuc;
var emptyFs = require('./utils').emptyFs;
function initPr(args) {
var omiCli = chalk.bold.cyan("Omi-Cli");
var isCn = isCnFun(args.language);
var customPrjName = args.project || '';
var tpl = join(__dirname, '../template/pr');
var dest = join(process.cwd(), customPrjName);
var projectName = basename(dest);
var mirror = args.mirror;
console.log();
console.log(omiCli + (!isCn ? " is booting... ": " 正在启动..."));
console.log(omiCli + (!isCn ? " will execute init-pr command... ": " 即将执行 init-pr 命令..."));
if(existsSync(dest) && !emptyDir.sync(dest)) {
console.log();
process.stdout.write(!isCn ? "This directory isn't empty, empty it? [Y/N] ": "此文件夹不为空,是否需要清空? [Y/N]: ");
process.stdin.resume();
process.stdin.setEncoding('utf-8');
process.stdin.on('data', (chunk) => {
chunk = chunk.replace(/\s\n|\r\n/g, '');
if(chunk !== 'y' && chunk !== 'Y') {
process.exit(0);
} else {
console.log(chalk.bold.cyan("Omi-Cli")+ (!isCn ? ' is emptying this directory...' : ' 正在清空此文件夹...'));
emptyFs(dest);
createPr()
}
});
} else {
createPr()
}
function createPr() {
console.log();
console.log(chalk.bold.cyan("Omi-Cli") + (!isCn ? ' will creating a new omi-pr in ' : ' 即将创建一个新的omi-pr在 ') + dest);
vfs.src(['**/*', '!mode_modules/**/*'], {cwd: tpl, cwdbase: true, dot: true})
.pipe(template(dest, tpl))
.pipe(vfs.dest(dest))
.on('end', function(){
try{
// info('Rename', 'gitignore -> .gitignore');
// renameSync(join(dest, 'gitignore'), join(dest, '.gitignore'));
if(customPrjName) {
try{
process.chdir(customPrjName);
}
catch (err) {
console.log(error(err));
}
}
info('Install', 'npm will install dependencies');
console.log();
require('./install')(mirror, done)
} catch(e){
console.log(error(e))
}
})
.resume();
}
function done(){
console.log();
console.log();
console.log();
success(`Congratulation! a Omi-pr has been created successful! `);
console.log(`
if you are not in ${projectName}, please run 'cd ${projectName}', then you can:
> ${chalk.bold.white('omi pr')} compile your project`);
console.log();
console.log(`${chalk.bold.cyan('Omi!')} https://alloyteam.github.io/omi` )
}
}
function template(dest, cwd) {
return through.obj(function (file, enc, cb) {
if (!file.stat.isFile()) {
return cb();
}
info('Copy', file.path.replace(cwd + '/', ''));
this.push(file);
cb();
});
}
module.exports = initPr;

View File

@ -1,96 +1,110 @@
var join = require('path').join;
var basename = require('path').basename;
var path = require('path');
var join = path.join;
var basename = path.basename;
var fs = require('fs');
var vfs = require('vinyl-fs');
var renameSync = require('fs').renameSync;
var renameSync = fs.renameSync;
var existsSync = fs.existsSync;
var chalk = require('chalk');
var through = require('through2');
var emptyDir = require('empty-dir');
var info = require('./logger').info;
var error = require('./logger').error;
var success = require('./logger').success;
var isCnFun = require('./utils').isCnFuc;
var emptyFs = require('./utils').emptyFs;
function init(program) {
var args = ['install'];
var customPrj = '';
if(program.args[0] && program.args[0] === "cn"){
args = ['install', "--registry", "https://registry.npm.taobao.org"];
} else if(program.args[1] && program.args[1] === "cn") {
customPrj = program.args[0];
args = ['install', "--registry", "https://registry.npm.taobao.org"];
} else {
customPrj = program.args[0] || '';
}
function init(args){
var omiCli = chalk.bold.cyan("Omi-Cli");
var isCn = isCnFun(args.language);
var customPrjName = args.project || '';
var tpl = join(__dirname, '../template/app');
var dest = join(process.cwd(), customPrj);
var dest = join(process.cwd(), customPrjName);
var projectName = basename(dest);
if (!customPrj && !emptyDir.sync(dest)) {
error('This directory existing files, please empty.');
process.exit(1);
}
var mirror = args.mirror;
console.log();
console.log(`Creating a new Omi app in ${dest}`);
console.log(omiCli + (!isCn ? " is booting... ": " 正在启动..."));
console.log(omiCli + (!isCn ? " will execute init command... ": " 即将执行 init 命令..."));
/*
* Use vinyl-fs to init file
* https://github.com/dvajs/dva-cli/blob/master/src/init.js
*/
vfs.src(['**/*', '!mode_modules/**/*'], {cwd: tpl, cwdbase: true, dot: true})
.pipe(template(dest, tpl))
.pipe(vfs.dest(dest))
.on('end', function(){
try{
info('Rename', 'gitignore -> .gitignore');
renameSync(join(dest, 'gitignore'), join(dest, '.gitignore'));
if(customPrj) {
try{
process.chdir(customPrj);
}
catch (err) {
console.log(error(err));
}}
info('Run', 'npm will install dependencies');
console.log();
require('./install')(args, echoDone)
} catch(e){
console.log(error(e))
if(existsSync(dest) && !emptyDir.sync(dest)) {
console.log();
process.stdout.write(!isCn ? "This directory isn't empty, empty it? [Y/N] ": "此文件夹不为空,是否需要清空? [Y/N]: ");
process.stdin.resume();
process.stdin.setEncoding('utf-8');
process.stdin.on('data', (chunk) => {
chunk = chunk.replace(/\s\n|\r\n/g, '');
if(chunk !== 'y' && chunk !== 'Y') {
process.exit(0);
} else {
console.log(chalk.bold.cyan("Omi-Cli")+ (!isCn ? ' is emptying this directory...' : ' 正在清空此文件夹...'));
emptyFs(dest);
createApp()
}
})
.resume();
});
} else {
createApp()
}
function echoDone(){
function createApp() {
console.log();
console.log(chalk.bold.cyan("Omi-Cli") + (!isCn ? ' will creating a new omi app in ' : ' 即将创建一个新的应用在 ') + dest);
vfs.src(['**/*', '!mode_modules/**/*'], {cwd: tpl, cwdbase: true, dot: true})
.pipe(template(dest, tpl))
.pipe(vfs.dest(dest))
.on('end', function(){
try{
info('Rename', 'gitignore -> .gitignore');
renameSync(join(dest, 'gitignore'), join(dest, '.gitignore'));
if(customPrjName) {
try{
process.chdir(customPrjName);
}
catch (err) {
console.log(error(err));
}
}
info('Install', 'npm will install dependencies');
console.log();
require('./install')(mirror, done)
} catch(e){
console.log(error(e))
}
})
.resume();
}
function done(){
console.log();
console.log();
console.log();
success(`Congratulation! "${projectName}" has been created successful! `);
console.log(`
Using the scaffold with Gulp + Webpack + Babel + BrowserSync,
In ${projectName}, you can run these commands:
> ${chalk.bold.white('npm run dev')} Starts the development server
> ${chalk.bold.white('npm run dist')} Publish your project`);
if you are not in ${projectName}, please run 'cd ${projectName}', then you can:
> ${chalk.bold.white('npm run dev')} Starts the development server
> ${chalk.bold.white('npm run dist')} Publish your project`);
console.log();
console.log(`${chalk.bold.cyan('Omi!')} https://alloyteam.github.io/omi` )
}
}
function template(dest, cwd) {
return through.obj(function (file, enc, cb) {
return through.obj(function (file, enc, cb) {
if (!file.stat.isFile()) {
return cb();
}
info('Copy', file.path.replace(cwd + '/', ''));
this.push(file);
cb();
});
this.push(file);
cb();
});
}
module.exports = init;

View File

@ -1,13 +1,20 @@
var spawn = require('cross-spawn');
var ora = require('ora');
module.exports = function (args, done){
var common = spawn('npm', args, { stdio: 'inherit' });
common.on('close', function () {
done();
process.exit(0);
});
common.on('error', function (reason) {
module.exports = function (mirror, done){
var registry;
if(mirror !== 'default'){
registry = ['--registry', require('./mirror')[mirror]];
}
secede(spawn('npm', registry ? [].concat(['install'], registry) : ['install'], { stdio: 'inherit'}));
};
function secede(line){
line.on('close', function(code){
process.exit(code)
})
line.on('error', function (reason) {
console.log('An error occured while executing the NPM command.', reason);
});
};
}

8
cli/lib/mirror.json Normal file
View File

@ -0,0 +1,8 @@
{
"npm": "https://registry.npmjs.org/",
"cnpm": "http://r.cnpmjs.org/",
"taobao": "https://registry.npm.taobao.org/",
"nj": "https://registry.nodejitsu.com/",
"rednpm": "http://registry.mirror.cqupt.edu.cn",
"skimdb": "https://skimdb.npmjs.com/registry"
}

121
cli/lib/omi-pr/build.js Normal file
View File

@ -0,0 +1,121 @@
const webpack = require('webpack')
const path = require('path')
const fs = require('fs')
let webpackConfig = require('./webpack.config.js')
let omiConfig = require(path.resolve('.')+"/omi.config.js")
const dir = path.resolve('.')
const compiler = webpack(webpackConfig)
const jsdom = require("jsdom").jsdom
const window = jsdom().defaultView
const keys = Object.keys(webpackConfig.entry)
const len = keys.length
let index = 0
let list = []
const build = () => {
compiler.run((err, stats) => {
if (err) {
console.error(err)
return
}
const jsonStats = stats.toJson()
if (jsonStats.errors.length > 0) {
const error = new Error(jsonStats.errors[0])
error.errors = jsonStats.errors
error.warnings = jsonStats.warnings
console.log(jsonStats)
return
}
getHTMLCSS(keys[index])
})
}
const getHTMLCSS = (name) =>{
window.document.head.innerHTML = ''
window.document.body.innerHTML = ''
window.Omi = null
let scriptEl = window.document.createElement("script");
scriptEl.onload = function () {
fs.unlinkSync(scriptEl.src)
list.push([window.document.head.innerHTML, '<div id="__omi">'+window.document.body.innerHTML.replace('<script src="'+scriptEl.src+'.js"><\/script>','')+'</div>',scriptEl.src])
index++
(index<len)&&getHTMLCSS(keys[index])
if(index===len){
cpLite()
}
}
scriptEl.src = name+".js"
window.document.body.appendChild(scriptEl)
}
const cpLite = ()=> {
webpackConfig.externals.omi = 'Omi'
const compilerEncludeOmi = webpack(webpackConfig)
compilerEncludeOmi.run((err, stats) => {
if (err) {
console.error(err)
return
}
const jsonStats = stats.toJson()
if (jsonStats.errors.length > 0) {
const error = new Error(jsonStats.errors[0])
error.errors = jsonStats.errors
error.warnings = jsonStats.warnings
console.error(err)
return
}
list.forEach((item)=> {
let name = item[2],
html = item[1],
css = item[0]
const content = fs.readFileSync(name, 'utf-8')
let newContent = JSON.stringify({component: content})
newContent = newContent.replace(/(\.render\([\s\S]*?\\['|"])(body)(\\['|"]\))/, ()=> {
return RegExp.$1 + '#__omi' + RegExp.$3
})
if (!fs.existsSync('dist')) {
fs.mkdirSync('dist')
}
let script = fs.readFileSync(path.resolve(__dirname, 'loadjs.js'), 'utf-8')
let tpl = fs.readFileSync( path.resolve('.')+'/src/page/tpl.html', 'utf-8')
let cdn = omiConfig['omi-cdn'];
if (!cdn) {
cdn = 'https://unpkg.com/omi@1.2.4/dist/omi.min.js'
}
fs.writeFileSync('dist/' + name.split('.')[0] + '.html',template(tpl, html, css ,`<script>var __OMI_DATA__=` + newContent + `</script><script>` + script.replace('{{omi-cdn}}', cdn) + `</script>`, 'utf-8'))
fs.unlinkSync(name)
})
//http://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color
console.log('\x1b[32m')
console.log('-------------------------------------------')
console.log('-------------------------------------------')
console.log('-----------Successfully Executed-----------')
console.log('-------------------------------------------')
console.log('-------------------------------------------')
console.log('\x1b[37m')
})
}
const template = (tpl,html,css,js)=>{
return tpl.replace('{{html}}',html).replace('{{css}}',css).replace('{{js}}',js)
}
module.exports = build;

15
cli/lib/omi-pr/loadjs.js Normal file
View File

@ -0,0 +1,15 @@
(function () {
load('{{omi-cdn}}',function (err) {
eval(__OMI_DATA__.component)
})
function load (src, fn) {
fn = fn || function () {}
var script = document.createElement('script')
script.src = src
script.onload = function () { fn(null) }
script.onerror = fn
script.crossorigin = 'anonymous'
document.head.appendChild(script)
}
})()

View File

@ -0,0 +1,78 @@
const path = require('path')
const webpack = require("webpack")
const commonChunkPlugin = webpack.optimize.CommonsChunkPlugin
const fs = require('fs')
let fileList = {};
walk(path.resolve('.')+'/src/page');
var config = {
entry: fileList,
output: {
filename: '[name].js'
},
//watch: true,
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ["babel-preset-es2015", "babel-preset-stage-0"].map(require.resolve),
//support ie8
plugins : [
"babel-plugin-transform-es3-property-literals",
"babel-plugin-transform-es3-member-expression-literals"
].map(require.resolve)
},
exclude: /(node_modules|bower_components)/
},
{test: /\.html|\.css$/, loader: "string-loader"}
]
},
plugins: [
// Avoid publishing files when compilation fails
new webpack.NoEmitOnErrorsPlugin()
],
stats: {
// Nice colored output
colors: true
},
externals: {
},
resolve: {
modules: [
path.join(__dirname, '..', 'node_modules'),
'node_modules',
path.join(__dirname, 'node_modules')
]
},
resolveLoader: {
modules: [
path.join(__dirname, '..', 'node_modules'),
'node_modules',
path.join(__dirname, 'node_modules')
]
}
// Create Sourcemaps for the bundle
//devtool: 'source-map'
};
config.plugins.push(new webpack.optimize.UglifyJsPlugin());
function walk(path){
var dirList = fs.readdirSync(path);
dirList.forEach(function(item){
if(fs.statSync(path + '/' + item).isDirectory()){
fileList[item] = path + '/' + item+'/main.js'
//walk(path + '/' + item);
}else{
//fileList.push(path + '/' + item);
}
});
}
module.exports = config;

26
cli/lib/pr.js Normal file
View File

@ -0,0 +1,26 @@
var fs = require('fs');
var chalk = require('chalk');
var join = require('path').join;
var existsSync = fs.existsSync;
function pr() {
var currentDir = process.cwd();
var srcPath = join(currentDir, 'src');
if(existsSync(srcPath)){
var build = require('./omi-pr/build');
console.log();
console.log(chalk.bold.cyan("Omi-Cli") + " is readying compiling...");
console.log();
build(currentDir)
} else {
console.log(chalk.bold.red("-------------------------------------------"));
console.log(chalk.bold.red("---------------- Path Error ---------------"));
console.log(chalk.bold.red("-------------------------------------------"));
process.exit(1);
}
}
module.exports = pr;

36
cli/lib/utils.js Normal file
View File

@ -0,0 +1,36 @@
var fs = require('fs');
var existsSync = fs.existsSync;
var readdirSync = fs.readdirSync;
var rmdirSync = fs.rmdirSync;
var unlinkSync = fs.unlinkSync;
var statSync = fs.statSync;
function isCnFuc(language){
return language === "cn" ? true : false
}
function emptyFs(path) {
var files = [];
var dir = [];
if(existsSync(path)){
files = readdirSync(path);
files.forEach(function (file, index) {
var curPath = path + "/" + file;
if(statSync(curPath).isDirectory()){
emptyFs(curPath)
} else {
unlinkSync(curPath);
}
});
dir = readdirSync(path);
dir.forEach(function (dirName, index) {
rmdirSync(path + "/" + dirName)
})
}
}
module.exports = {
isCnFuc: isCnFuc,
emptyFs: emptyFs
};

View File

@ -1,6 +1,6 @@
{
"name": "omi-cli",
"version": "0.2.6",
"version": "0.2.7",
"description": "CLI for scaffolding Omi.js projects.",
"main": "bin/omi",
"engines": {
@ -21,16 +21,22 @@
"author": "pasturn",
"license": "MIT",
"dependencies": {
"babel-plugin-transform-es3-member-expression-literals": "^6.22.0",
"babel-plugin-transform-es3-property-literals": "^6.22.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"chalk": "^1.1.3",
"commander": "^2.9.0",
"cross-npm-spawn": "^1.1.1",
"cross-spawn": "^5.0.1",
"empty-dir": "^0.2.1",
"fs-exists-sync": "^0.1.0",
"jsdom": "^9.12.0",
"ora": "^1.1.0",
"vinyl-fs": "^2.4.4"
"vinyl-fs": "^2.4.4",
"webpack": "^2.3.3"
},
"bugs": {
"bugs": {
"url": "https://github.com/AlloyTeam/omi/issues"
},
"homepage": "https://github.com/AlloyTeam/omi#readme"