-
Notifications
You must be signed in to change notification settings - Fork 230
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
lewischeng
committed
Aug 17, 2017
1 parent
8573659
commit febe1c3
Showing
21 changed files
with
739 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
root = true | ||
|
||
[*] | ||
end_of_line = lf | ||
charset = utf-8 | ||
trim_trailing_whitespace = true | ||
|
||
[{lib,src,test}/**.js] | ||
indent_style = space | ||
indent_size = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* text eol=lf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
.idea/ | ||
.DS_Store | ||
node_modules | ||
npm-debug.log | ||
npm-debug.log | ||
debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#!/usr/bin/env node | ||
|
||
'use strict'; | ||
|
||
require('../lib/feflow')(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
'use strict'; | ||
|
||
const Promise = require('bluebird'); | ||
const abbrev = require('abbrev'); | ||
|
||
class Command { | ||
|
||
constructor() { | ||
this.store = {}; | ||
this.alias = {}; | ||
} | ||
|
||
get(name) { | ||
name = name.toLowerCase(); | ||
return this.store[this.alias[name]]; | ||
} | ||
|
||
list() { | ||
return this.store; | ||
} | ||
|
||
register(name, desc, options, fn) { | ||
if (!name) throw new TypeError('name is required'); | ||
|
||
if (!fn) { | ||
if (options) { | ||
if (typeof options === 'function') { | ||
fn = options; | ||
|
||
if (typeof desc === 'object') { // name, options, fn | ||
options = desc; | ||
desc = ''; | ||
} else { // name, desc, fn | ||
options = {}; | ||
} | ||
} else { | ||
throw new TypeError('fn must be a function'); | ||
} | ||
} else { | ||
// name, fn | ||
if (typeof desc === 'function') { | ||
fn = desc; | ||
options = {}; | ||
desc = ''; | ||
} else { | ||
throw new TypeError('fn must be a function'); | ||
} | ||
} | ||
} | ||
|
||
if (fn.length > 1) { | ||
fn = Promise.promisify(fn); | ||
} else { | ||
fn = Promise.method(fn); | ||
} | ||
|
||
const c = this.store[name.toLowerCase()] = fn; | ||
c.options = options; | ||
c.desc = desc; | ||
|
||
this.alias = abbrev(Object.keys(this.store)); | ||
} | ||
} | ||
|
||
module.exports = Command; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
'use strict'; | ||
|
||
const vm = require('vm'); | ||
const pathFn = require('path'); | ||
const Module = require('module'); | ||
const _ = require('lodash'); | ||
const osenv = require('osenv'); | ||
const Promise = require('bluebird'); | ||
const chalk = require('chalk'); | ||
const fs = require('hexo-fs'); | ||
const logger = require('../utils/logger'); | ||
const Command = require('./command'); | ||
const pkg = require('../../package.json'); | ||
const sep = pathFn.sep; | ||
|
||
class Feflow { | ||
|
||
/** | ||
* Set root and plugin path, context variable include log, cli command object. | ||
* @param args | ||
*/ | ||
constructor(args) { | ||
args = args || {}; | ||
|
||
const base = pathFn.join(osenv.home(), './.feflow'); | ||
|
||
this.version = pkg.version; | ||
this.baseDir = base + sep; | ||
this.pkgPath = pathFn.join(base, 'package.json'); | ||
this.pluginDir = pathFn.join(base, 'node_modules') + sep; | ||
|
||
this.log = logger({ | ||
debug: Boolean(args.debug) | ||
}); | ||
|
||
this.cmd = new Command(); | ||
} | ||
|
||
/** | ||
* Read config and load internal and external plugins. | ||
*/ | ||
init() { | ||
const self = this; | ||
|
||
this.log.debug('Feflow version: %s', chalk.magenta(this.version)); | ||
|
||
// Load internal plugins | ||
require('../plugins/console')(this); | ||
require('../plugins/generator')(this); | ||
require('../plugins/install')(this); | ||
|
||
// Load external plugins | ||
return Promise.each([ | ||
'load_plugins' | ||
], function(name) { | ||
return require('./' + name)(self); | ||
}).then(function() { | ||
// Init success | ||
self.log.debug('init success!'); | ||
}); | ||
|
||
} | ||
|
||
/** | ||
* Call a command in console. | ||
* @param name | ||
* @param args | ||
* @param callback | ||
*/ | ||
call(name, args, callback) { | ||
if (!callback && typeof args === 'function') { | ||
callback = args; | ||
args = {}; | ||
} | ||
|
||
const self = this; | ||
|
||
return new Promise(function(resolve, reject) { | ||
const c = self.cmd.get(name); | ||
|
||
if (c) { | ||
c.call(self, args).then(resolve, reject); | ||
} else { | ||
reject(new Error('Command `' + name + '` has not been registered yet!')); | ||
} | ||
}).asCallback(callback); | ||
} | ||
|
||
/** | ||
* Load a plugin with vm module and inject feflow variable, | ||
* feflow is an instance and has context environment. | ||
* | ||
* @param path {String} Plugin path | ||
* @param callback {Function} Callback | ||
*/ | ||
loadPlugin(path, callback) { | ||
const self = this; | ||
|
||
return fs.readFile(path).then((script) => { | ||
|
||
const module = new Module(path); | ||
module.filename = path; | ||
module.paths = Module._nodeModulePaths(path); | ||
|
||
function require(path) { | ||
return module.require(path); | ||
} | ||
|
||
require.resolve = function(request) { | ||
return Module._resolveFilename(request, module); | ||
}; | ||
|
||
require.main = process.mainModule; | ||
require.extensions = Module._extensions; | ||
require.cache = Module._cache; | ||
|
||
// Inject feflow variable | ||
script = '(function(exports, require, module, __filename, __dirname, feflow){' + | ||
script + '});'; | ||
|
||
const fn = vm.runInThisContext(script, path); | ||
|
||
return fn(module.exports, require, module, path, pathFn.dirname(path), self); | ||
}).asCallback(callback); | ||
} | ||
} | ||
|
||
module.exports = Feflow; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
'use strict'; | ||
|
||
const pathFn = require('path'); | ||
const fs = require('hexo-fs'); | ||
const Promise = require('bluebird'); | ||
const chalk = require('chalk'); | ||
|
||
module.exports = function(ctx) { | ||
return Promise.all([ | ||
loadModules(ctx) | ||
]); | ||
}; | ||
|
||
function loadModules(ctx) { | ||
const self = this; | ||
const pluginDir = ctx.pluginDir; | ||
|
||
return loadModuleList(ctx).map(function(name) { | ||
let path = require.resolve(pathFn.join(pluginDir, name)); | ||
|
||
// Load plugins | ||
return ctx.loadPlugin(path).then(function() { | ||
ctx.log.debug('Plugin loaded: %s', chalk.magenta(name)); | ||
}).catch(function(err) { | ||
ctx.log.error({err: err}, 'Plugin load failed: %s', chalk.magenta(name)); | ||
}); | ||
}); | ||
} | ||
|
||
function loadModuleList(ctx) { | ||
const packagePath = pathFn.join(ctx.baseDir, 'package.json'); | ||
const pluginDir = ctx.pluginDir; | ||
|
||
// Make sure package.json exists | ||
return fs.exists(packagePath).then(function(exist) { | ||
if (!exist) return []; | ||
|
||
// Read package.json and find dependencies | ||
return fs.readFile(packagePath).then(function(content) { | ||
const json = JSON.parse(content); | ||
const deps = json.dependencies || json.devDependencies || {}; | ||
|
||
return Object.keys(deps); | ||
}); | ||
}).filter(function(name) { | ||
// Ignore plugins whose name is not started with "feflow-plugin-" | ||
if (!/^feflow-plugin-|^@[^/]+\/feflow-plugin-/.test(name)) return false; | ||
|
||
// Make sure the plugin exists | ||
const path = pathFn.join(pluginDir, name); | ||
return fs.exists(path); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
'use strict'; | ||
|
||
const Feflow = require('./core'); | ||
const minimist = require('minimist'); | ||
|
||
function entry(args) { | ||
args = minimist(process.argv.slice(2)); | ||
|
||
const feflow = new Feflow(args); | ||
const log = feflow.log; | ||
|
||
function handleError(err) { | ||
if (err) { | ||
log.fatal(err); | ||
} | ||
|
||
process.exit(2); | ||
} | ||
|
||
return feflow.init().then(function() { | ||
let cmd = ''; | ||
|
||
if (!args.h && !args.help) { | ||
cmd = args._.shift(); | ||
|
||
if (cmd) { | ||
let c = feflow.cmd.get(cmd); | ||
if (!c) cmd = 'help'; | ||
} else { | ||
cmd = 'help'; | ||
} | ||
} else { | ||
cmd = 'help'; | ||
} | ||
|
||
return feflow.call(cmd, args).then(function() { | ||
|
||
}).catch(function(err) { | ||
console.log(err); | ||
}); | ||
}).catch(handleError); | ||
} | ||
|
||
module.exports = entry; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
'use strict'; | ||
const meow = require('meow'); | ||
|
||
function helpConsole(args) { | ||
const cli = meow(` | ||
Usage: feflow [options] [command] | ||
Commands: | ||
init Choose a scaffold to initialize project. | ||
install <plugin> Install a plugin or a yeoman generator. | ||
publish Publish files to cdn or offline package. | ||
jb Publish to jb when in development. | ||
ars --env Publish to ars code platform, env is daily, pre or prod. | ||
Options: | ||
--version, -[vV] Print version and exit successfully. | ||
--help, -[hH] Print this help and exit successfully. | ||
Report bugs to http://git.code.oa.com/feflow/discussion/issues. | ||
`); | ||
|
||
return cli.showHelp(1); | ||
} | ||
|
||
module.exports = helpConsole; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
'use strict'; | ||
|
||
module.exports = function(ctx) { | ||
|
||
const cmd = ctx.cmd; | ||
|
||
cmd.register('help', 'Get help on a command.', {}, require('./help')); | ||
|
||
cmd.register('version', 'Display version information.', {}, require('./version')); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
'use strict'; | ||
|
||
const os = require('os'); | ||
const Promise = require('bluebird'); | ||
|
||
function versionConsole(args) { | ||
const versions = process.versions; | ||
const keys = Object.keys(versions); | ||
let key = ''; | ||
|
||
console.log('feflow:', this.version); | ||
console.log('os:', os.type(), os.release(), os.platform(), os.arch()); | ||
|
||
for (let i = 0, len = keys.length; i < len; i++) { | ||
key = keys[i]; | ||
console.log('%s: %s', key, versions[key]); | ||
} | ||
|
||
return Promise.resolve(); | ||
} | ||
|
||
module.exports = versionConsole; |
Oops, something went wrong.