Skip to content
Browse files

updated binaries

  • Loading branch information...
1 parent fd14f5b commit 28f22a65e8bf84183882263520ac7ea19471c3db @Shogun147 committed Dec 25, 2013
Showing with 560 additions and 453 deletions.
  1. +55 −78 bin/create
  2. +95 −0 bin/generate
  3. +48 −51 bin/katana
  4. +340 −317 bin/modules
  5. +10 −0 template/app.js
  6. +4 −3 template/app/config/development/app.js
  7. +8 −4 template/app/controllers/home.js
View
133 bin/create 100755 → 100644
@@ -1,111 +1,88 @@
#!/usr/bin/env node
-var Path = require('path');
-var Fs = require('fs');
-var spawn = require('child_process').spawn;
+var Path = require('path');
+var Fs = require('fs');
-var mod_root = Path.normalize(__dirname + '/../');
-var root = process.cwd() + Path.sep;
-var eol = require('os').EOL;
+var async = require('async');
-var info = require(mod_root +'package.json');
+var spawn = require('child_process').spawn;
+var confirm = require('../lib/utils').confirm;
-var Async = require('async');
-var mkdir = require('mkdirp');
-var copy = require('../lib/utils').copy;
+var fs = require('../lib/fs');
+var mkdir = fs.mkdir;
+var copy = fs.copy;
+var walk = fs.walk;
+var find = fs.find;
+var remove = fs.remove;
-var App = require('commander');
-
-App.version(info.version);
-
-var Err = function(message) {
- console.log(eol, message);
+var node = process.execPath;
+var root = process.cwd() + Path.sep;
+var modRoot = Path.join(__dirname, '..') + Path.sep;
+var eol = require('os').EOL;
+var sep = Path.sep;
- process.exit();
-}
+var version = require('../package').version;
-App.command('create [path]')
-.description('create katana application')
-.action(function(path) {
- path = path ? Path.resolve(root, path) + Path.sep : root;
+require('colors');
- App.confirm('Create application at: '+ path +' ? [Yes|No]: ', function(ok) {
- if (!ok) { process.exit(); }
-
- Async.series([
- function(callback) {
- mkdir(path, 0755, function(error) {
- callback(error);
- });
- },
- function(callback) {
- Fs.readdir(mod_root +'template', function(error, items) {
- if (error) { return callback(error); }
+var App = require('commander');
- var pending = items.length;
+App.command('create')
+.description('create new katana application')
+.action(function(name) {
+ if (arguments.length < 2) {
+ name = null;
+ }
- if (!pending) { return callback(); }
+ var path = Path.join(root, name || '');
- items.forEach(function(item) {
- copy(mod_root +'template/' + item, path + item, function(error) {
- if (error) { console.log(error); }
+ confirm(' Create app at '+ path.blue +' ? ', function(error, ok) {
+ if (!ok) { return; }
- if (!--pending) {
- callback();
- }
- });
- });
- });
+ // TOOD: check if directory already exists and remove on confirmation?
+ async.series([
+ function(next) {
+ copy(Path.join(__dirname, '..', 'template'), path, next);
},
- function(callback) {
+ function(next) {
var paths = [
- path + 'app/config/production',
- path + 'app/models',
- path + 'public/images',
- path + 'public/scripts',
- path + 'public/css',
- path + 'modules',
- path + 'temp/files'
- ];
-
- Async.forEach(paths, function(path, cb) {
- mkdir(path, 0777, function(error) {
- if (error) { console.log('Warning:'.magenta, 'could not create directory:', path); }
-
- cb();
- })
- }, function(error) {
- callback(error);
+ 'app/config/production',
+ 'app/models',
+ 'public/images',
+ 'public/scripts',
+ 'public/css',
+ 'modules',
+ 'temp/files'
+ ].map(function(dir) {
+ return Path.join(path, dir);
});
+
+ async.each(paths, mkdir, next);
},
- function(callback) {
+ function(next) {
var pack = {
- name: 'katana-app',
+ name: 'app',
version: '0.0.1',
- private: true,
dependencies: {
- katana: info.version,
+ katana: version,
joose: '*',
ejs: '*'
},
katana: {
modules: {}
}
};
-
- Fs.writeFile(path +'package.json', JSON.stringify(pack, null, 2), function(error) {
- if (error) { console.log('Warning:'.magenta, ' could not write package.json file!'); }
- callback();
- });
+ Fs.writeFile(Path.join(path, 'package.json'), JSON.stringify(pack, null, 2), next);
+ }
+ ], function(error) {
+ if (error) {
+ return console.log(error);
}
- ], function(error, results) {
- if (error) { return Err(error); }
-
- console.log('App created! Run "npm install" under app root to install dependencies.');
- process.exit();
- })
+ console.log(' Done!'.green, 'Your new app is at', path.blue +'.');
+ console.log(' Run', '"npm install"'.blue, 'under app root to install dependencies.');
+ });
});
});
View
95 bin/generate
@@ -0,0 +1,95 @@
+#!/usr/bin/env node
+
+var Path = require('path');
+var Fs = require('fs');
+
+var inherits = require('util').inherits;
+var spawn = require('child_process').spawn;
+
+var fs = require('../lib/fs');
+var mkdir = fs.mkdir;
+
+require('colors');
+
+var node = process.execPath;
+var root = process.cwd() + Path.sep;
+var modRoot = Path.join(__dirname, '..') + Path.sep;
+var isWin = process.platform === 'win32';
+var eol = require('os').EOL;
+var sep = Path.sep;
+
+var modules = require('../modules');
+
+function AppError(message) {
+ Error.apply(this, arguments);
+ this.name = 'AppError';
+ this.message = message || '';
+}
+inherits(AppError, Error);
+
+process.on('uncaughtException', function(error) {
+ if (error instanceof AppError) {
+ console.error(' Error:'.red, error.message);
+ } else {
+ console.error(error.stack || error.message || error);
+ }
+ //process.stdin.pause();
+ process.exit(1);
+});
+
+var App = require('commander');
+
+App.command('controller <name>')
+.description('create new controller')
+.action(function(controller, action) {
+ var module = 'app';
+ var path = 'app'+ sep +'controllers';
+ var name = Path.basename(controller);
+ var actions = action.parent.rawArgs.slice(4);
+
+ if (controller.indexOf(':') !== -1) {
+ controller = controller.split(':');
+ module = controller[0];
+ controller = controller[1];
+ path = ['modules', module, 'controllers'].join(sep);
+
+ if (!modules[module]) {
+ throw new AppError('Module not found!');
+ }
+ }
+
+ path = Path.join(root, path, Path.dirname(controller));
+
+ actions = actions.map(function(method) {
+ return ' '+ method + ': function(request, response) { '+ eol+eol +' }';
+ });
+
+ var content = [
+ 'var '+ name +'Controller = Class({',
+ ' isa: App.Controller,'+ eol,
+ ' methods: {',
+ actions.join(','+ eol+eol),
+ ' }',
+ '});'+ eol,
+ 'module.exports = new '+ name +'Controller;'+ eol
+ ].join(eol);
+
+ mkdir(path, function(error) {
+ if (error) {
+ throw new AppError('Failed to create controller directory!');
+ }
+
+ path = Path.join(path, name + '.js');
+ Fs.exists(path, function(exists) {
+ if (exists) { throw new AppError('This controller already exists!'); }
+
+ Fs.writeFile(path, content, function(error) {
+ if (error) { throw error; }
+
+ console.log(' Done!'.green, 'Controller', Path.relative(root, path).blue, 'created!');
+ });
+ });
+ });
+});
+
+App.parse(process.argv);
View
99 bin/katana
@@ -2,80 +2,77 @@
var Path = require('path');
-var mod_root = Path.normalize(__dirname + '/../');
-var root = process.cwd() + Path.sep;
-var eol = require('os').EOL;
-
var spawn = require('child_process').spawn;
+var node = process.execPath;
+var root = process.cwd() + Path.sep;
+var modRoot = Path.join(__dirname, '..') + Path.sep;
+var eol = require('os').EOL;
+var sep = Path.sep;
+
+require('colors');
+
var App = require('commander');
-App.version(require(mod_root + 'package').version);
-App.usage('katana <command> [options]');
+App.version(require('../package').version);
+App.usage('<command> [options]');
App.on('--help', function() {
- console.log(' Commands:'+ eol);
- console.log(' create [path] - create katana application');
- console.log(' module - list all available modules');
- console.log(' module install <name> [url] - install module');
- console.log(' module update - update modules list and info');
- console.log(' module <str> - search modules');
- console.log(' module enable <name> - enable module');
- console.log(' module disable <name> - disable module');
- console.log(' module uninstall <name> - uninstall module'+ eol);
-
- process.exit();
+ console.log([
+ ' Commands:'+ eol,
+ 'new|create|init [path] create new katana application',
+ 'modules list available modules',
+ 'modules update update modules list',
+ 'modules search <str> search modules',
+ 'module install <name> [url] install module',
+ 'install <name> [url] shortcut for "module install"',
+ 'module enable <name> enable module',
+ 'module disable <name> disable module',
+ 'module uninstall|remove uninstall module',
+ 'controller|ctrl <name> [methods] generate new controller, optional methods list',
+ eol
+ ].join(eol +' '));
});
App.parse(process.argv);
-var args = process.argv.slice(3);
-
-var command = App.args[0];
+!App.args.length && App.help();
-if (!command) {
- process.stdout.write(App.helpInformation());
-
- App.emit('--help');
-
- process.exit();
-}
+var command = App.args.shift();
if (command === 'module') {
command = 'modules';
+} else if (command === 'install') {
+ App.args.unshift('install');
+ command = 'modules';
+} else if (command==='init' || command==='new') {
+ App.args.unshift('create');
+ command = 'create';
+} else if (command==='controller' || command==='ctrl') {
+ App.args.unshift('controller');
+ command = 'generate';
}
-var commands = ['create', 'modules'];
-
-if (commands.indexOf(command) === -1) {
- console.log('Error: unknown command. Run --help to list available commands.');
-
- process.exit();
+if (['create', 'modules', 'generate'].indexOf(command) === -1) {
+ console.error(' Error:'.red, 'Unknown command. Run "katana --help" to list available commands!');
+ process.exit(1);
}
-if (command === 'create' || (command !== 'create' && !args.length)) {
- args.unshift(command);
+if (command==='modules' && !App.args.length) {
+ App.args.unshift('list');
}
-var bin = Path.join(mod_root, 'bin', command);
-
-var proc = spawn('node', [bin].concat(args), {
+var proc = spawn(node, [Path.join(modRoot, 'bin', command)].concat(App.args), {
cwd: root,
stdio: 'inherit'
});
-try {
- ['SIGTERM', 'SIGINT', 'SIGHUP', 'SIGQUIT'].forEach(function(signal) {
- process.on(signal, function() {
- if (proc) {
- proc.kill(signal);
- }
+proc.on('close', function(code, signal) {
+ process.exit();
+});
- process.exit();
- });
+['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'].forEach(function(signal) {
+ process.on(signal, function() {
+ proc && proc.kill(signal);
});
-} catch(e) {}
-
-process.stdin.end(); // possible bug when using stdin.destroy from commander commands callback
-
-App.parse(process.argv);
+});
View
657 bin/modules 100755 → 100644
@@ -1,453 +1,476 @@
#!/usr/bin/env node
-var Path = require('path');
-var Fs = require('fs');
-var spawn = require('child_process').spawn;
-
-var mod_root = Path.normalize(__dirname + '/../');
-var root = process.cwd() + Path.sep;
-var eol = require('os').EOL;
+var Path = require('path');
+var Fs = require('fs');
-var Async = require('async');
-var request = require('request');
-var mkdir = require('mkdirp');
-var colors = require('colors');
-var copy = require('../lib/utils').copy;
-var rand_str = require('../lib/utils').rand_str;
-var load = require('../lib/utils').load;
-var remove = require('../lib/utils').remove;
-var check = require('../lib/utils').validator;
+var request = require('request');
+var async = require('async');
+var semver = require('semver');
var zlib = require('zlib');
var tar = require('tar');
var gzip = zlib.createUnzip();
-var semver = require('semver');
+var inherits = require('util').inherits;
+var spawn = require('child_process').spawn;
+var utils = require('../lib/utils');
+var confirm = utils.confirm;
+var check = utils.validator;
+
+var fs = require('../lib/fs');
+var mkdir = fs.mkdir;
+var copy = fs.copy;
+var walk = fs.walk;
+var find = fs.find;
+var move = fs.move;
+var remove = fs.remove;
+
+require('colors');
+
+var node = process.execPath;
+var root = process.cwd() + Path.sep;
+var modRoot = Path.join(__dirname, '..') + Path.sep;
+var isWin = process.platform === 'win32';
+var eol = require('os').EOL;
+var sep = Path.sep;
+
+var modules = require('../modules');
+
+function AppError(message) {
+ Error.apply(this, arguments);
+ this.name = 'AppError';
+ this.message = message || '';
+}
+inherits(AppError, Error);
-var info = require(mod_root +'package.json');
-var modules = require(mod_root +'modules.json');
+process.on('uncaughtException', function(error) {
+ if (error instanceof AppError) {
+ console.error(' Error:'.red, error.message);
+ } else {
+ console.error(error.stack || error.message || error);
+ }
+ //process.stdin.pause();
+ process.exit(1);
+});
var App = require('commander');
-App.version(info.version);
-
-var Err = function(message) {
- console.log(eol, message);
-
- process.exit();
-}
-
-App.command('modules')
-.description('list all available modules')
+App.command('list')
+.description('list available modules')
.action(function() {
- var pack;
- var total = 0;
+ var meta = {
+ total: Object.keys(modules).length,
+ installed: 0,
+ enabled: 0
+ };
+ var pack = null;
try {
- pack = require(root +'package.json').katana;
+ pack = (require(Path.join(root, 'package.json'))).katana;
} catch(error) {}
+ var i = 0;
for (var name in modules) {
- total++;
-
var module = modules[name];
+ var installed = pack && pack.modules[name]!== undefined;
+ var enabled = pack && pack.modules[name]!==undefined && pack.modules[name].enabled;
- console.log('\n#'+ total, name, '-', module.description);
- console.log(' author:', module.author.name, '<'+ module.author.email +'>');
- console.log(' tags:', module.tags.length ? module.tags.join(' ') : 'no tags, download master branch');
+ module.tags.reverse();
+ installed && meta.installed++;
+ enabled && meta.enabled++;
- if (pack !== undefined) {
- var installed = pack.modules[name] !== undefined;
- var enabled = pack.modules[name]!==undefined && pack.modules[name].enabled===true;
+ var url = module.url || (['https://github.com', module.github.username, module.github.repository, 'tarball', module.tags[0] || 'master'].join('/'));
- console.log(' installed:', installed ? 'true'.green : 'false'.yellow, ' enabled:', enabled ? 'true'.green : 'false'.yellow);
- }
+ console.log('\n #'.grey + ++i, name, (installed ? '■installed'.blue : '') + (enabled ? ' ■enabled'.green : ''));
+ console.log(' title:'.grey, module.description);
+ console.log(' author:'.grey, module.author.name, '<'+ module.author.email +'>');
+ console.log(' url:'.grey, url);
+ console.log(' tags:'.grey, module.tags.length ? module.tags.join('') : 'master');
}
- if (!total) {
- console.log('There are no modules available.');
- }
-});
-
-App.command('update')
-.description('update modules list and info')
-.action(function() {
- var url = 'https://raw.github.com/Shogun147/Katana/master/modules.json';
+ // meta.total && console.log('\n ■Total:'.blue + meta.total, '■Installed:'.magenta + meta.installed, '■Enabled:'.green + meta.enabled);
- request(url).on('response', function(response) {
- if (response.statusCode !== 200 && response.statusCode !== 304) {
- return Err('Error: url not found or error while downloading it.');
- }
- }).pipe(Fs.createWriteStream(mod_root + 'modules.json')).on('error', function(error) {
- Err(error);
- }).on('error', function(error) {
- Err(error);
- }).on('end', function() {
- console.log('Done! Run "katana modules" to view updated modules list.');
-
- process.exit();
- });
+ console.log(!meta.total ? '\n **There are no available modules**\n'.grey : '');
+ !meta.total && console.log(' Tip:'.blue +' run "'.grey +'katana modules update'.green +'" - to update modules list and info.'.grey, '\n');
});
-App.command('search <contain>')
+App.command('search <query>')
.description('search modules')
-.action(function(contain) {
- var pack;
- var total = 0;
-
+.action(function(query) {
+ var meta = {
+ total: 0,
+ installed: 0,
+ enabled: 0
+ };
+
+ var pack = null;
try {
- pack = require(root +'package.json').katana;
+ pack = (require(Path.join(root, 'package.json'))).katana;
} catch(error) {}
+ var i = 0;
for (var name in modules) {
var module = modules[name];
-
- var regexp = new RegExp(contain, 'ig');
+ var regexp = new RegExp(query, 'ig');
- if (regexp.test(module.name) || regexp.test(module.description)) {
- total++;
+ if (regexp.test(name) || regexp.test(module.description)) {
+ var installed = pack && pack.modules[name]!==undefined;
+ var enabled = pack && pack.modules[name]!==undefined && pack.modules[name].enabled;
- console.log('#'+ total, name, '-', module.description);
- console.log(' author:', module.author.name, '<'+ module.author.email +'>');
- console.log(' tags:', module.tags.length ? module.tags.join(' ') : 'no tags, download master branch');
+ meta.total++;
+ module.tags.reverse();
+ installed && meta.installed++;
+ enabled && meta.enabled++;
- if (pack !== undefined) {
- var installed = pack.modules[name] !== undefined;
- var enabled = pack.modules[name]!==undefined && pack.modules[name].enabled===true;
+ var url = module.url || (['https://github.com', module.github.username, module.github.repository, 'tarball', module.tags[0] || 'master'].join('/'));
- console.log(' installed:', installed ? 'true'.green : 'false'.yellow, ' enabled:', enabled ? 'true'.green : 'false'.yellow);
- }
+ console.log('\n #'.grey + ++i, name, (installed ? '■installed'.blue : '') + (enabled ? ' ■enabled'.green : ''));
+ console.log(' title:'.grey, module.description);
+ console.log(' author:'.grey, module.author.name, '<'+ module.author.email +'>');
+ console.log(' url:'.grey, url);
+ console.log(' tags:'.grey, module.tags.length ? module.tags.join('') : 'master');
}
}
- if (!total) {
- console.log(' There are no modules that match your search request.');
- }
+ console.log(!meta.total ? '\n **No modules found which match "'.grey+ query +'"**\n'.grey : '');
+ !meta.total && console.log(' Tip:'.blue +' run "'.grey +'katana modules update'.green +'" - to update modules list and info.'.grey, '\n');
});
-// name@version - installs from modules.json registry, optional version
-// name username:name@version - install from github username and repo-name, optional version
-// name url - install as name from url
+App.command('update')
+.description('update modules list and info')
+.action(function() {
+ var url = 'https://raw.github.com/Shogun147/Katana/master/modules.json';
+
+ console.log(' Downloading:', url);
+ request({ url: url, timeout: 5000 })
+ .on('response', function(response) {
+ if (response.statusCode!==200 && response.statusCode!==304) {
+ throw new AppError('Request failed with status code '+ response.statusCode.toString().blue +'!');
+ }
+
+ this.pipe(Fs.createWriteStream(modRoot + 'modules.json')
+ .on('finish', function() {
+ console.log(' Done!'.green, 'Run', '"katana modules"'.blue, 'to list modules.');
+ })).on('error', function(error) {
+ throw new AppError('Updating failed with '+ (error.message || error.toString).yellow +'.');
+ });
+ }).on('error', function(error) {
+ throw new AppError(error.code === 'ETIMEDOUT' ? 'Request timeout!' : 'Request failed with '+ error.code.yellow +'!');
+ });
+});
App.command('install <name> [url]')
.description('install or reinstall application module')
.action(function(name, url) {
var ProgressBar = require('progress');
- var Bar;
-
- var username, version;
+ var Bar = null;
+ var req = null;
+ var username = null;
+ var version = null;
- if ((!check(url, 'isUrl') || !url) && name.indexOf('@') !== -1) {
- name = name.split('@');
+ try {
+ var pack = require(Path.join(root, 'package')).katana;
+ !pack.modules && (pack.modules = {});
+ } catch(error) {
+ throw new AppError('Not a Katana application!');
+ }
+ if ((!url || !check(url, 'isUrl')) && name.indexOf('@') !== -1) {
+ name = name.split('@');
version = name[1];
name = name[0];
if (!semver.valid(version)) {
- return Err('Error:'.red, ' invalid version!');
+ throw new AppError('Invalid version!');
}
}
if (url && !check(url, 'isUrl')) {
if (url.indexOf(':') === -1) {
- return Err('Error:'.red, ' invalid url or github username:repository!');
+ throw new AppError('Invalid url or Github username:repository!')
}
var repository = url.split(':');
-
- username = repository[0];
- repository = repository[1];
+ username = repository[0];
+ repository = repository[1];
if (!repository) {
- return Err('Error: invalid repository name!');
+ throw new AppError('Invalid repository name!');
}
if (repository.indexOf('@') !== -1) {
- version = repository.split('@')[1];
+ version = repository.split('@')[1];
repository = repository.split('@')[0];
if (!semver.valid(version)) {
- return Err('Error: invalid version!');
+ throw new AppError('Invalid version!');
}
}
- url = 'https://github.com/'+ username +'/'+ repository +'/tarball/'+ (version || 'master');
+ url = ['https://github.com', username, repository, 'tarball', version || 'master'].join('/');
}
- check_installed(name, function(ok, exists) {
- if(!ok) { return process.exit(); }
+ async.series([
+ function(next) {
+ if (!pack.modules[name]) { return next(); }
- if (!username && !url && !modules[name]) {
- return Err('Error: Module ['+ name +'] not found!')
- }
+ confirm(' Warning: '.yellow + 'This module is already installed, do you want to replace it? ', function(error, ok) {
+ if (!ok) { process.exit(); }
- if (!username && !url) {
- var module = modules[name];
-
- if (version && module.tags.indexOf(version) === -1) {
- return Err('Error: there\'s no '+ version +' version for module ['+ name +']');
+ var isFile = !Fs.existsSync(Path.join(root, 'modules', name));
+ remove(Path.join(root, 'modules', name + (isFile ? '.js' : '')), next);
+ });
+ },
+ function(next) {
+ if (!username && !url && !modules[name]) {
+ return next('Module '+ name.blue +' not found!');
}
- if (!version && module.tags.length) {
- version = module.tags.pop();
+ if (!username && !url) {
+ var module = modules[name];
+ if (version && module.tags.indexOf(version) === -1) {
+ return next('There\'s no '+ version.blue +' version for module '+ name.blue +'!');
+ }
+ if (!version && module.tags.length) {
+ version = module.tags.pop();
+ }
+ if (module.url) {
+ url = module.url.replace(':version', version || 'master');
+ } else {
+ url = ['https://github.com', module.github.username, module.github.repository, 'tarball', version || 'master'].join('/');
+ }
}
- url = module.url ? module.url + (version || 'master') : 'https://github.com/'+ module.github.username +'/'+ module.github.repository +'/tarball/'+ (version || 'master');
- }
-
- console.log(' name: ', name);
- console.log(' version: ', version);
- console.log('username: ', username);
- console.log(' url: ', url);
-
- mkdir(root + 'temp/modules/'+ name, 0777, function(error) {
- if (error) { return Err('Error: could not create temporary directory.\n'+ error); }
-
- request({ url: url })
+ next();
+ },
+ function(next) {
+ mkdir(Path.join(root, 'temp', 'modules', name), 0777, next);
+ },
+ function(next) {
+ console.log(' Downloading:', url.blue);
+ req = request({ url: url, timeout: 10000 })
+ .on('error', function(error) {
+ next(error.code==='ETIMEDOUT' ? 'Request timeout!' : error);
+ })
.on('response', function(response) {
if (response.statusCode !== 200 && response.statusCode !== 304) {
this.abort();
-
- return Err('Error: module not found! Server responded with status code: '+ response.statusCode);
+ return next('Module request failed! Server responded with '+ response.statusCode.toString().blue +'.');
}
if (response.headers['content-type'] !== 'application/x-gzip') {
this.abort();
-
- return Err('Error: the server should respond with content-type application/x-gzip, '+ response.headers['content-type'] +' given.');
+ return next('Module request failed! Unexpected content type, module must be gzipped tar-ball.');
}
- var length = parseInt(response.headers['content-length'], 10);
-
- Bar = new ProgressBar('\n downloading [:bar] :percent :etas', {
+ Bar = new ProgressBar(' :etas'.blue +' [:bar] ' + ':percent'.green + eol, {
complete: '=',
incomplete: ' ',
width: 40,
- total: length
+ total: parseInt(response.headers['content-length'], 10)
});
- }).on('data', function(chunk) {
- if (this._aborted) { return; }
-
- Bar.tick(chunk.length);
- }).pipe(zlib.createUnzip()).on('error', function(error) {
- Err('Error: \n'+ error);
- }).pipe(tar.Extract({ path: root +'temp/modules/'+ name })).on('error', function(error) {
- Err('Error: \n'+ error);
- }).on('end', function() {
- Fs.readdir(Path.join(root, 'temp', 'modules', name), function(error, items) {
- if (error || !items.length) { return Err('Error: '+ (error ? eol + error : 'module extracting failed!')); }
-
- var tmp = items[0];
- var is_file = false;
-
- Fs.readdir(Path.join(root, 'temp', 'modules', name, tmp), function(error, items) {
- var pending = items.length;
-
- Async.series([
- function(callback) {
- if (pending === 1) {
- var item = items[0];
-
- is_file = true;
-
- copy(root +'temp/modules/'+ name +'/'+ tmp +'/'+ item, root +'modules/'+ item, function(error) {
- callback(error);
- });
- } else {
- Fs.mkdir(Path.join(root, 'modules', name), 0777, function(error) {
- if (error) { return callback(error); }
-
- items.forEach(function(item) {
- copy(root +'temp/modules/'+ name +'/'+ tmp +'/'+ item, root +'modules/'+ name +'/'+ item, function(error) {
- if (error) { console.log(error); }
-
- if (!--pending) {
- callback();
- }
- });
- });
- });
- }
- },
- function(callback) {
- remove(root +'temp/modules/'+ name, function(error) {
- if (error) { console.log('Warning:'.magento, 'could not remove temporary directory.'); }
-
- callback();
- });
- },
- function(callback) {
- if (is_file) { return callback(); }
-
- Fs.readdir(Path.join(root, 'modules', name, 'hooks'), function(error, hooks) {
- if (error) { return callback(); }
-
- var pending = hooks.length;
-
- if (!pending) { return callback(); }
-
- hooks.forEach(function(hook) {
- Fs.chmod(Path.join(root, 'modules', name, 'hooks', hook), '+x', function(error) {
- if (error) { console.log('Warning:'.magento, 'could not make hook "'+ hook +'" executable.'); }
-
- if (!--pending) {
- callback();
- }
- });
- });
- });
- },
- function(callback) {
- run_hook('install', name, function(error) {
- if (error) { console.log('Error while running install hook:\n', error); }
-
- callback();
- });
- }
- ], function(error) {
- if (error) {
- return Err(error);
- }
-
- var pack = require(root +'package.json');
-
- var v;
-
- try {
- var v = require(root +'modules/'+ name +'/package.json').version;
- } catch(error) {}
-
- pack.katana.modules[name] = {
- version: v || version || null,
- enabled: false
- }
-
- Fs.writeFile(root +'package.json', JSON.stringify(pack, null, 2), function(error) {
- console.log('\nModule "'+ name +'" now installed! Run "katana module enable '+ name +'" to enable it.');
-
- process.exit();
- });
- });
- });
+
+ req.on('data', function(chunk) {
+ Bar.tick(chunk.length);
});
+
+ function abort() {
+ req.abort();
+ next('Extracting failed!');
+ }
+
+ var zlibStream = zlib.createUnzip();
+ var tarStream = tar.Extract({ path: Path.join(root, 'temp', 'modules', name) });
+
+ zlibStream.on('error', abort);
+ tarStream.on('error', abort).on('end', next);
+
+ req.pipe(zlibStream);
+ zlibStream.pipe(tarStream);
});
- });
- });
-});
+ },
+ function(next) {
+ var path = Path.join(root, 'temp', 'modules', name);
+ Fs.readdir(path, function(error, item) {
+ if (error || !item.length) { return next(error || 'Extracting failed or module archive empty.'); }
-function check_installed(name, callback) {
- Fs.exists(Path.join(root, 'modules', name), function(exists) {
- if (!exists) {
- return callback(true, false);
- }
+ var isFile = Path.extname(item[0]) === '.js';
- App.confirm('Module '+ name +' already installed, did you want to continue and rewrite old one? [Yes|No] ', function(ok) {
- remove(root +'modules/'+ name, function(error) {
- if (error) {
- return Err('Error:'.red, 'could not remove existing module directory!');
+ move(Path.join(path, item[0]), Path.join(root, 'modules', name + (isFile ? '.js' : '')), next);
+ });
+ },
+ function(next) {
+ remove(Path.join(root, 'temp', 'modules', name), function(error) {
+ if (error) { console.log('Error: Failed to remove temp directory!'); }
+
+ next();
+ });
+ },
+ function(next) {
+ if (isWin) { return next(); }
+
+ var path = Path.join(root, 'modules', name, 'hooks');
+
+ Fs.readdir(path, function(error, hooks) {
+ if (error) { return next(error.code==='ENOENT' ? null : error); }
+
+ async.each(hooks, function(hook, cb) {
+ Fs.chmod(Path.join(path, hook), 0755, function(error) {
+ if (error) {
+ console.log(' Warning:'.yellow, 'Failed to make hook '+ hook.blue +' executable!');
+ }
+
+ cb();
+ });
+ }, next);
+ });
+ },
+ function(next) {
+ return next();
+
+ var path = Path.join(__dirname, 'modules', 'auth');
+
+ process.chdir(path);
+ require('npm').load(function(error, Npm) {
+ Npm.config.set('logLevel', 'info')
+ .on('log', function(message) {
+ console.log(message);
+ }).install(function(error) {
+ console.log(arguments);
+ process.chdir(root);
+ });
+ });
+ },
+ function(next) {
+ runHook('install', name, function(code, signal) {
+ if (code) {
+ // TODO: need some more descriptive message here
+ console.log(' Warning:'.yellow, 'Install hook exited with code', code.blue +'!');
}
- callback(ok, true);
+ next();
});
- });
- });
-}
+ },
+ function(next) {
+ var pack = require(root + 'package.json');
-App.command('enable <name>')
-.description('enable module')
-.action(function(module) {
- run_hook('enable', module, function(error) {
- if (error) { return Err(error); }
+ pack.katana.modules[name] = {
+ version: version || 'master',
+ enabled: false
+ };
- var pack = require(root +'package.json');
+ Fs.writeFile(root +'package.json', JSON.stringify(pack, null, 2), function(error) {
+ if (error) {
+ console.log(' Warning:'.yellow, 'Failed to update package.json file with new installed module.');
+ }
- pack.katana.modules[module].enabled = true;
+ next();
+ });
+ }
+ ], function(error) {
+ if (error) {
+ if (error instanceof Error) {
+ throw error;
+ } else { throw new AppError(error); }
+ }
- Fs.writeFile(root +'package.json', JSON.stringify(pack, null, 2), function(error) {
- if (error) { return Err(error); }
+ console.log(' Done!'.green, 'Module', name.blue, 'installed!');
+ console.log(' Run', '"katana module enable '.blue+ name.blue +'"'.blue, 'to enable this module.');
- console.log('Done! Module "'+ module +'" now', 'enabled'.green, '!');
- });
+ // find where we still have stdin opened
+ process.stdin.pause();
});
});
+App.command('enable <name>')
+.description('enable module')
+.action(function(name) {
+ toggleModule(name, 'enable');
+});
+
App.command('disable <name>')
.description('disable module')
-.action(function(module) {
- run_hook('disable', module, function(error) {
- if (error) { return Err(error); }
+.action(function(name) {
+ toggleModule(name, 'disable');
+});
+
+function toggleModule(name, action) {
+ var pack = require(root + 'package.json');
- var pack = require(root +'package.json');
+ if (!pack.katana.modules[name]) {
+ throw new AppError('This module is not installed!');
+ }
- pack.katana.modules[module].enabled = false;
+ runHook(action, name, function(code) {
+ if (code) {
+ console.log(' Warning:'.yellow, action +' hook exited with code', code.toString().blue +'!');
+ }
- Fs.writeFile(root +'package.json', JSON.stringify(pack, null, 2), function(error) {
- if (error) { return Err(error); }
+ pack.katana.modules[name].enabled = action === 'enable';
- console.log('Done! Module "'+ module +'" now', 'disabled'.yellow, '!');
+ Fs.writeFile(root + 'package.json', JSON.stringify(pack, null, 2), function(error) {
+ if (error) { throw error; }
+
+ console.log('Done! Module', name.blue, 'now', (action==='enable' ? 'enabled'.green : 'disabled'.yellow) +'.');
});
});
-});
+}
App.command('uninstall <name>')
-.description('remove module')
-.action(function(module) {
- run_hook('uninstall', module, function(error) {
- if (error) { return Err(error); }
+.description('uninstall module')
+.action(function(name) {
+ var pack = require(root + 'package.json');
- var path = Path.join(root, 'modules', module);
+ if (!pack.katana.modules[name]) {
+ throw new AppError('This module is not installed!');
+ }
- if (Fs.existsSync(path +'.js')) {
- path += '.js';
+ runHook('uninstall', name, function(code) {
+ if (code) {
+ console.log(' Warning:'.yellow, 'Uninstall hook exited with code', code.toString().blue +'!');
}
- remove(path, function(error) {
- if (error) { return Err(error); }
-
- var pack = require(root +'package.json');
+ var isFile = !Fs.existsSync(Path.join(root, 'modules', name));
+ remove(Path.join(root, 'modules', name + (isFile ? '.js' : '')), function(error) {
+ if (error) {
+ console.log(' Warning:'.yellow, 'Error removing module directory.');
+ }
- delete pack.katana.modules[module];
+ delete pack.katana.modules[name];
- Fs.writeFile(root +'package.json', JSON.stringify(pack, null, 2), function(error) {
- if (error) { return Err(error); }
-
- console.log('Done! Module "'+ module +'"', 'removed'.red, '!');
+ Fs.writeFile(root + 'package.json', JSON.stringify(pack, null, 2), function(error) {
+ console.log(' Done!'.green, 'Module', name.blue, 'uninstalled!');
});
- })
+ });
});
});
-var run_hook = function(name, module, callback) {
- Fs.exists(Path.join(root, 'modules', module, 'hooks', name +'.js'), function(exists) {
- if (!exists) { return callback(); }
+function runHook(hook, module, next) {
+ hook = Path.join(root, 'modules', module, 'hooks', hook);
+ hook = Fs.existsSync(hook) ? hook : (Fs.existsSync(hook +'.js') ? hook +'.js' : null);
- var hook = spawn('node', [Path.join(root, 'modules', module, 'hooks', name +'.js')], {
- cwd: root,
- stdio: 'inherit'
- });
+ if (!hook) { return next(); }
- hook.on('exit', function(code) {
- if (code) {
- return callback('Something goes wrong. Hook exited with code: '+ code);
- }
-
- callback();
- });
+ var hookProc = spawn(node, [hook], {
+ cwd: root,
+ stdio: 'inherit'
+ });
- try {
- ['SIGTERM', 'SIGINT', 'SIGHUP', 'SIGQUIT'].forEach(function(signal) {
- process.on(signal, function() {
- if (hook) {
- hook.kill(signal);
- }
+ var done = false;
+ hookProc.on('close', function(code, signal) {
+ done ? process.exit() : next(code, signal);
+ });
- process.exit();
- });
- });
- } catch(e) {
- // callback(e);
- }
+ ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'].forEach(function(signal) {
+ process.on(signal, function() {
+ done = true;
+ hookProc && hookProc.kill(signal);
+ });
});
}
+if (process.argv[2] === 'remove') {
+ process.argv[2] = 'uninstall';
+}
+
App.parse(process.argv);
View
10 template/app.js
@@ -1,2 +1,12 @@
require('joose');
require('katana');
+
+process.title = 'Node: '+ App.info.name;
+
+App.use(function(request, response, next) {
+ response.on('header', function() {
+ response.setHeader('X-Powered-By', 'Katana v'+ App.version);
+ });
+
+ next();
+});
View
7 template/app/config/development/app.js
@@ -1,6 +1,7 @@
-var Fs = require('fs');
+var Path = require('path');
+var Fs = require('fs');
-var root = process.cwd() + '/';
+var root = process.cwd() + Path.sep;
module.exports = {
url: 'localhost',
@@ -83,7 +84,7 @@ module.exports = {
maxFields: 1000,
maxFieldsSize: 2 * 1024 * 1024,
- uploadDir: root + 'temp/files',
+ uploadDir: Path.join(root, 'temp', 'files'),
keepExtensions: false,
encoding: 'utf-8',
View
12 template/app/controllers/home.js
@@ -1,10 +1,14 @@
var HomeController = Class({
isa: App.Controller,
-
+
methods: {
- index: function(request, response) {
- response.render('index', { title: 'Katana - Easy to use, modular web framework for any Node.js samurai.' });
- }
+ index: function(request, response) {
+ var data = {
+ title: 'Katana - Easy to use, modular web framework for any Node.js samurai.'
+ };
+
+ response.render('index', data);
+ }
}
});

0 comments on commit 28f22a6

Please sign in to comment.
Something went wrong with that request. Please try again.