/* webfan (C) Till Wehowski, Webfan.de - All rights reserved. */
const EXITCODE_OK = 0;
const EXITCODE_HALT = 1;
const EXITCODE_ERROR = 2;
const EXITCODE_NOTREADY = 3;
const EXITCODE_SQLERROR = 5;
(function(){
'use strict';
function _cli(argv, options, switches, positionalSwitches, shells){
'use strict';
function f(code){
return '(function(result){'+code+'})';
}
var util = require('util'); /* frdl.util;*/
var escapeshellarg = frdl.escapeshellarg;
var fNFin = null;
var finalized = false;
var _CLI = new frdl.EventEmitter();
_CLI.config = require('../clisetup/clisetup');
var optparse = require('optparse-js/lib/optparse');
if(!util.isArray(argv) && !!util.isString(argv) ){
argv = _CLI.config.parseArgs(argv);
}
var debug=function(type, obj){
var opts = {
showHidden : true,
depth : 4
};
try{
var color = 'black';
if('warn'===type)color = 'orange';
if('error'===type || 'fatal'===type)color = 'red';
if('dir'===type)color = 'blue';
var str = '<p><legend style="color:'+color+';">'+type+'</legend>'+util.inspect(obj, opts)+'</p>';
console[type](str);
frdl.alert[('error'===type || 'warn'===type)?'error':'log'](str);
}catch(err){
console.warn(err);
}
};
/*
try{
var mask = require('16:webfan/webfat/js/flagmask');
console.dir('dir', mask);
}catch(err){
frdl.alert.error(err);
}
*/
_CLI.options = _CLI.config.default_options;
if(null!==options && 'object' === typeof options){
_CLI.options = frdl.extend(_CLI.options, options);
}
var doParse = true;
var exitcode = EXITCODE_NOTREADY;
exitcode=EXITCODE_OK;
var parser = null;
/* var _CLI = this || Object.create({});
var _CLI = Object.create({}); */
var messageLog = [];
var errorlog = [];
_CLI.escapeshellarg = escapeshellarg;
_CLI.finalState = _CLI.required([
'firstarg'
], function (dataArray) {
console.log('CLI exit with ' + exitcode);
if(0<exitcode && 200 !== exitcode){
_CLI.emit('catch', exitcode.toString()+' : '+_CLI.errorlog.join('\s\n\r'));
}else{
_CLI.emit('success', _CLI.data.data);
}
}, _CLI);
_CLI.finalState.add('parse');
_CLI.finalState.add('exit');
_CLI.finalState.add('finalize.before');
_CLI.finalState.add('finalize');
_CLI.on('catch', function(err){
try{
_CLI.finalState.cancel();
}catch(err){
}
});
if('undefined' === typeof shells && null !== sessionStorage.getItem('webfan/cli $ shells') ){
shells = JSON.parse(sessionStorage.getItem('webfan/cli $ shells'));
}
_CLI.shell = '$ webfan';
_CLI.shells = $.extend({
'$ webfan' : {
url : '16:webfan/cli/commands/webfan/'
},
'$ test' : {
url : '16:webfan/cli/commands/test/'
},
'$ apc' : {
url : '16:frdl/webfan/cli/commands/apc/'
}
//, '$ exampleshell' : {
// url : 'http://example.com/example-path/commands/exampleshell/'
//}
//'$ frdl' : {
//error (used by other cli)
//},
//'$ flow' : {
//},
//'$ js' : {
//}
}, (shells || {}));
sessionStorage.setItem('webfan/cli $ shells', JSON.stringify(_CLI.shells));
if(null !== sessionStorage.getItem('webfan/cli $ shell') && 'undefined' !== typeof _CLI.shells[sessionStorage.getItem('webfan/cli $ shell')]){
_CLI.shell = sessionStorage.getItem('webfan/cli $ shell');
}
_CLI.WinID = 'cli.html';
_CLI.cmd = null;
_CLI.argv = argv;
_CLI.callbackName = false;
_CLI.data = {
DIRECTORIES : [],
FILES : [],
URLS : [],
ACTION : null,
data : null,
options : {
}
};
_CLI.switches = switches || [
// ['--$ [TEXT]', "Change shell"]
];
var _tokensToBuild = [];
var _filtersToBuild = [];
var _sfn = {
};
_CLI.positionalSwitches = positionalSwitches || [];
_CLI.addOption = function(optName, description, callback, filterStr, _short){
if('string' !== typeof filterStr)var filterStr = ' [TEXT]';
if('string'===typeof _short){
_CLI.switches.push([_short, '--' + optName + filterStr, description]);
}else{
_CLI.switches.push(['--' + optName + filterStr, description]);
}
_sfn[optName] = callback;
return _CLI;
};
_CLI.filter = function(filterName, filter){
_filtersToBuild.push([filterName, filter]);
return _CLI;
};
_CLI.addToken = function(option, arg, fn){
_tokensToBuild.push([option, arg, fn]);
return _CLI;
};
try{
Object.defineProperty(_CLI, 'exitcode', {
get : function(){
return ((0===_CLI.errorlog.length)
? EXITCODE_OK
: (EXITCODE_OK<exitcode) ? /* ++exitcode */ exitcode : EXITCODE_ERROR);
},
set : function(val){
throw 'write to cli.exitcode from public scope';
}
});
Object.defineProperty(_CLI, 'messageLog', {
get : function(){
return messageLog;
},
set : function(val){
console.warn('Do not set cli.messageLog manually!');
}
});
Object.defineProperty(_CLI, 'errorlog', {
get : function(){
return errorlog;
},
set : function(val){
console.warn('Do not set cli.errorlog manually!');
}
});
Object.defineProperty(_CLI, 'util', {
get : function(){
return frdl.util;
},
set : function(val){
console.warn('Do not set cli.util manually!');
}
});
}catch(err){
if(Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) {
this.__defineGetter__('exitcode', function(){
return ((0===_CLI.errorlog.length)
? 0
: (0===exitcode) ? ++exitcode : exitcode);
} );
this.__defineSetter__('exitcode', function(val){
throw 'write to cli.exitcode from public scope';
} );
this.__defineGetter__('messageLog', function(){
return messageLog;
} );
this.__defineSetter__('messageLog', function(val){
console.warn('Do not set cli.messageLog manually!');
} );
this.__defineGetter__('errorlog', function(){
return errorlog;
} );
this.__defineSetter__('errorlog', function(val){
console.warn('Do not set cli.errorlog manually!');
} );
this.__defineGetter__('util', function(){
return frdl.util;
} );
this.__defineSetter__('util', function(val){
console.warn('Do not set cli.util manually!');
} );
}else{
console.deprecated('Missing Object.defineProperty and Object.prototype.__defineGetter__ - Fallback to UNSAFE configuration readable!');
_CLI.exitcode = exitcode;
_CLI.messageLog = messageLog;
_CLI.errorlog = errorlog;
_CLI.util = frdl.util;
}
}
_CLI.log = function(m){
_CLI.emit('log', m);
};
_CLI.error = function(m){
_CLI.emit('error', m);
};
var Finalize = function(scope, THAT){
if(!!finalized)return;
finalized=true;
if(true === THAT.options.debug) _CLI.log('>>>Finalize<<<');
if(true === THAT.parser._halt){
// if(true === THAT.options.debug) _CLI.log('>>>HALT<<<');
// return;
}
/*if(!THAT.parser._halt)*/_CLI.emit('finalize.before', THAT);
/* if(!THAT.parser._halt)*/_CLI.emit('finalize', THAT);
if(true === THAT.options.debug) _CLI.log('>>>RESULT BEGIN<<<');
if(true === THAT.options.debug) _CLI.log(JSON.stringify(THAT.result));
if(true === THAT.options.debug) _CLI.log('>>>RESULT END<<<');
};
if(!!_CLI.options.defaults.onceFinalize){
_CLI.once('finalize', function(THAT){
if('function'===typeof fNFin && !THAT.parser._halt){
fNFin.call(_CLI, THAT);
}
_CLI.emit('exit', _CLI.exitcode);
});
}
var onHalt = function(tokens){
_CLI.emit('exit', EXITCODE_HALT);
if(true === THAT.options.debug) _CLI.log('>>>HALT<<<');
if(true === _CLI.options.debug)_CLI.log(JSON.stringify(_CLI.data.rest));
};
var Test=function(THAT){
THAT.result = 'This is any testresult!';
_CLI.log('Run the "test" command');
};
if(!!_CLI.options.defaults.logs){
_CLI.on('log', function(m){
messageLog.push(m);
console.log(m);
});
_CLI.on('error', function(m){
errorlog.push(m);
console.error(m);
});
}
_CLI.cmd = _CLI.argv[0].trim();
var __changeShell = function(s){
var _shellName = '$ ' + s;
if('undefined'===typeof _CLI.shells[_shellName]){
_CLI.emit('error', 'Shell ' + _shellName + ' is not installed!');
return;
}
_CLI.shell = _shellName;
sessionStorage.setItem('webfan/cli $ shell', _shellName);
};
// e.g.: --$ webfan
_CLI.addToken('$', '*', function(c, result_length, token, current_option){
__changeShell(token);
});
if(!!_CLI.options.defaults.sql){
if('noop' === _CLI.cmd.toLowerCase()){
// doParse=false;
fNFin = function(){};
}
if('frdl' === _CLI.cmd.toLowerCase()){
var _args = frdl.clone(_CLI.argv);
_args.shift();
_CLI.finalState.add('api response');
var _cmd = _args.join(' ');
_cmd += ' --format="json" ';
doParse=false;
fNFin = function(){
if(null===sessionStorage.getItem('api_url')){
_CLI.emit('catch', 'No api_url specified');
return;
}
$.ajax( {
url: sessionStorage.getItem('api_url'),
crossDomain: true,
cache:false,
headers: {'X-Requested-With': 'XMLHttpRequest'
},
type: 'POST',
dataType: 'json',
data: {
cmd : _cmd,
format : 'application/json'
}
} )
.done(function(response) {
_CLI.data.data = response;
})
.fail(function(jqXHR, textStatus) {
_CLI.emit('catch', 'Error: ' + jqXHR.status+ ' ' + jqXHR.statusText);
})
.always(function() {
_CLI.emit('api response');
});
};
}
frdl.each(_CLI.config.sqlstarts, function(i, command){
if(_CLI.cmd.toLowerCase() === command){
doParse=false;
fNFin = function(){
_CLI.emit('sql',_CLI.argv.join(' '));
};
// _CLI.emit('exit');
return false;
}
});
_CLI.on('sql', function(query){
console.log('cli>sql '+query);
try{
var sql = frdl.sql;
var _sqlState = 'sql ' + frdl.Sha1.hash(query + '.' + frdl.Guid.newGuid());
_CLI.finalState.add(_sqlState);
(function runSQL(){
if(!sql || 'function' !== typeof sql.query){
webfan.$Async(function(){
runSQL();
},1);
return;
}
sql.query(query, function(err, result) {
if (err) {
_CLI.error(err);
_CLI.emit(_sqlState, false);
return;
}
var _Result = result;
// _CLI.once('finalize.before', function(THAT){
if(null===_CLI.data.data){
_CLI.data.data =_Result;
}else if(true === _Result instanceof Array && true === _CLI.data.data instanceof Array){
_CLI.data.data.push(_Result);
}else{
_CLI.data.data =_Result;
}
//});
_CLI.emit(_sqlState, _Result);
});
}());
} catch(err) {
_CLI.error(err);
}
});
}
if(!!_CLI.options.defaults.sql){
_CLI.addOption('sql', 'Run a sql query', function(name, value) {
_CLI.emit('sql',value, false);
}, ' [TEXT]');
}
if(!!_CLI.options.defaults.firstArg && '--$' !== _CLI.cmd && '$' !== _CLI.cmd){
try{
var cli;
//if(null===fNFin)cli = require('16:webfan/cli/commands/webfan/'+_CLI.cmd);
try{
if(null===fNFin)cli = require( _CLI.shells[_CLI.shell].url + _CLI.cmd );
}catch(err){
if(null===fNFin)cli = require('16:webfan/cli/commands/webfan/'+_CLI.cmd);
}
if('function' === typeof cli.prepare)cli.prepare(_CLI);
fNFin = ('function' === typeof cli.finalize) ? cli.finalize : fNFin;
}catch(err){
//_CLI.error('Command "'+_CLI.cmd+'" not found. '+err);
}
}
_CLI.emit('firstarg', _CLI.cmd);
_CLI.exit = function(exitcode){
_CLI.emit('exit', exitcode)
return _CLI;
};
_CLI.once('exit', function(_exitcode){
_CLI.parser._halt=true;
if('undefined' === typeof _exitcode)_exitcode = _CLI.exitcode;
if(isNaN(_exitcode)){
throw 'exitcode is not a number';
}
exitcode=_exitcode;
// _CLI.parser.on_halt.apply(_CLI.parser, [_CLI.data.data]);
// if(0<exitcode && 200 !== exitcode){
// fNFin = null;
// _CLI.emit('catch', exitcode.toString()+' : '+_CLI.errorlog.join('\s\n\r'));
// }else{
// if(!finalized){
// _CLI.finalize(_CLI);
// }
// _CLI.emit('success', _CLI.data.data);
// }
});
if(!!_CLI.options.defaults.standards){
_CLI.addOption('debug', 'Debug mode', function(name, value) {
_CLI.options.debug = value;
if(!_CLI.options.debug){
frdl.debug.mode(3);
}
}, ' [SWITCH]', '-d')
.addOption('help', 'Shows help', function() {
var txt = _CLI.parser.toString();
txt += '\n\r';
txt += Object.keys(_CLI.shells).toString();
_CLI.log(txt);
_CLI.data.data=txt;
}, ' [SWITCH]', '-h')
.addOption('callback', 'Poplulate a callback function to the global.frdl.cbs[CALLBACKVALUE] if not exists already\nand call it with result as arguments finally,\nafter that remove the function from the frdl.cbs stack',
function(name, value) {
if(/^\w+$/.test(value)){
var c = _CLI.callbackName = value;
_CLI.once('finalize', function(r){
if('function'===typeof frdl.cbs[_CLI.callbackName]){
frdl.cbs[_CLI.callbackName].apply(_CLI, [r]);
}
});
return;
}
try{
var callback = eval(f(value));
_CLI.once('finalize', function(r){
callback.apply(_CLI, [r]);
});
}catch(err){
_CLI.error(err);
}
/*
var fTok = '()=>', fTok2 = '=>';
if(fTok === value.substr(0,fTok.length)){
var t = value.substr(fTok.length,value.length);
try{
var callback = eval(f(t));
_CLI.once('finalize', function(r){
callback.apply(_CLI, [r]);
});
}catch(err){
console.warn(err);
}
return;
}else if(fTok2 === value.substr(0,fTok2.length)){
var t = value.substr(fTok2.length,value.length);
try{
var callback = eval(f(t));
_CLI.once('finalize', function(r){
callback.apply(_CLI, [r]);
});
}catch(err){
console.warn(err);
}
return;
}
if('undefined' === typeof frdl.cbs[c]){
frdl.cbs[c] = function(result){
var util = require('util');
var opts = {
showHidden : true,
depth : 4
};
var type = (result && null !== result) ? 'log' : 'error';
try{
var color = 'black';
if('warn'===type)color = 'orange';
if('error'===type || 'fatal'===type)color = 'red';
if('dir'===type)color = 'blue';
frdl.alert[('error'===type)?'error':'log']('<p><legend style="color:'+color+';">'+type+'</legend>'+util.inspect(result, opts)+'</p>');
frdl.cbs[c] = undefined;
}catch(err){
console.warn(err);
}
};
}
*/
}, ' [CALLBACK]')
.addOption('dir', 'Take a directory', function(name, value) {
_CLI.data.DIRECTORIES.push(value);
_CLI.emit('op.dir', value);
}, ' [DIRECTORY]')
.addOption('file', 'Take a file', function(name, value) {
_CLI.data.FILES.push(value);
_CLI.emit('op.file', value);
}, ' [FILE]')
/**
_CLI.addOption('test', 'Run a test', function(name, value) {
finalized=true;
alert(name+'='+value);
}, ' [TEXT]');
frdl.fs5.polyfill.getFiler().cd(frdl.fs5.polyfill.getFiler().fs.root);
fs.mkdir(dir, '0755', function(err,dirEntry) {
if(err){
console.warn(err);
}else{
console.log('mdir ' + dir);
}
});
*/
.addOption('mkdir', 'Create directory', function(name, value) {
var fs = require('fs');
frdl.fs5.polyfill.getFiler().cd(frdl.fs5.polyfill.getFiler().fs.root);
fs.mkdir(value, '0755', function(err,dirEntry) {
if(err){
_CLI.error(err);
}else{
_CLI.log('mdir ' + value);
_CLI.emit('op.mkdir success', value);
}
});
_CLI.emit('op.mkdir', value);
}, ' [TEXT]')
.addOption('rmdir', 'Remove directory', function(name, value) {
var fs = require('fs');
frdl.fs5.polyfill.getFiler().cd(frdl.fs5.polyfill.getFiler().fs.root);
fs.rmdir(value, function(err,dirEntry) {
if(err){
_CLI.error(err);
}else{
_CLI.log('rmdir ' + value);
_CLI.emit('op.rmdir success', value);
}
});
_CLI.emit('op.rmdir', value);
}, ' [TEXT]')
.addOption('unlink', 'Remove file', function(name, value) {
var fs = require('fs');
frdl.fs5.polyfill.getFiler().cd(frdl.fs5.polyfill.getFiler().fs.root);
fs.unlink(value, function(err,dirEntry) {
if(err){
_CLI.error(err);
}else{
_CLI.log('unlink ' + value);
_CLI.emit('op.unlink success', value);
}
});
_CLI.emit('op.unlink', value);
}, ' [TEXT]')
.addToken('*', 'sql_close', function(c, result_length, token, current_option){
frdl.sql.query('COMMIT', function(err, data){
if(err){
console.error(err);
return;
}
frdl.alert.log('Closing sql in 10 seconds...');
webfan.$Async(function(){
frdl.sql.close();
frdl.alert.log('sql closed-');
},10000);
});
})
.addOption('sql_free', 'Free a sql table or database from memory', function(name, value) {
frdl.sql.sql_free(value);
}, ' [TEXT]')
.addOption('api_url', 'Set api_url', function(name, value) {
sessionStorage.setItem('api_url', value);
}, ' [TEXT]')
;
}
//ende of !!defaults.standards
_CLI.parser = parser = new optparse(_CLI.switches);
_CLI.parser.banner = 'Usage: webfan.exe [[$|!#]shell] [arguments]';
_CLI.parser.halt(function(tokens) {
return onHalt(tokens);
});
_CLI.filter('CALLBACK', function(value) {
var fTok = '()=>', fTok2 = '=>', t = false;
if(fTok === value.substr(0,fTok.length)){
t = value.substr(fTok.length,value.length);
}else if(fTok2 === value.substr(0,fTok2.length)){
t = value.substr(fTok2.length,value.length);
}
try{
return (!t && !!_CLI.util.isString(value) )
|| ('string'===typeof t && !!_CLI.util.isFunction(eval(f(t))) )
? value
: undefined
;
}catch(err){
if(0<frdl.debug.mode())console.warn(err);
return (!t && !!_CLI.util.isString(value) )
? value
: undefined
;
}
})
.filter('SQLQUERY', function(value) {
return value;
})
.filter('DIRECTORY', function(value) {
//value = _CLI.escapeshellarg (value);
if(!frdl.nw)return value;
var fs = require('fs');
var stats = fs.statSync(value);
if(true !== stats.isDirectory()) throw "Directory "+value+' does not exist.';
return value;
})
.filter('FILE', function(value) {
// value = _CLI.escapeshellarg (value);
if(!frdl.nw)return value;
var fs = require('fs');
var stats = fs.statSync(value);
if(true !== stats.isFile()) throw "File "+value+' does not exist.';
return value;
})
.filter('SWITCH', function(value) {
return _CLI.util.StringToBoolean(value);
})
;
try{
var parse = function(argv){
frdl.each(_filtersToBuild, function(i, f){
_CLI.parser.filter(f[0], f[1]);
});
_CLI.positionalSwitches.forEach(function($switch, $position, $switches){
_CLI.parser.on($position, $switch);
});
var k;
for(k in _sfn){
_CLI.parser.on(k, _sfn[k]);
}
frdl.each(_tokensToBuild, function(i, t){
_CLI.parser.token(t[0], t[1], t[2]);
});
_CLI.parser.on('*', function(opt, value) {
if(true === _CLI.options.debug)_CLI.log('Passing argument ' + opt + '=' + value);
if(!_CLI.data.options[opt]){
_CLI.data.options[opt] = value;
}else{
if(!_CLI.data.options[opt].length){
_CLI.data.options[opt] = [_CLI.data.options[opt]];
}
_CLI.data.options[opt].push(value);
}
});
var pr = _CLI.parser.parse(_CLI.argv);
_CLI.emit('parse', pr);
return pr;
};
_CLI.finalize = function(scope){
if('undefined' === typeof scope)var scope = _CLI;
Finalize(scope, _CLI);
};
if(!!doParse){
parse(_CLI.argv);
}else{
_CLI.emit('parse', []);
}
}catch(err){
_CLI.error(err);
}
return _CLI;
}
exports = module.exports = _cli;
}());
|