Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don't worry, you can still create the pull request.
  • 3 commits
  • 40 files changed
  • 0 commit comments
  • 1 contributor
Commits on Dec 02, 2011
@contra contra nodester v2 scaffold 5734a2b
Commits on Dec 06, 2011
@contra contra simplification of commando code 3fbbf78
Commits on Dec 07, 2011
@contra contra help fix 2be0381
Showing with 215 additions and 1,345 deletions.
  1. +4 −0 CHANGELOG.md
  2. +15 −0 LICENSE
  3. +16 −18 README.md
  4. +36 −0 TODO.md
  5. +49 −0 bin/cli.coffee
  6. +0 −12 bin/nodester.js
  7. 0  commands/app/alias.coffee
  8. 0  commands/app/aliases.coffee
  9. 0  commands/app/info.coffee
  10. 0  commands/app/install.coffee
  11. 0  commands/app/link.coffee
  12. 0  commands/app/logs.coffee
  13. 0  commands/app/push.coffee
  14. 0  commands/app/restart.coffee
  15. 0  commands/app/start.coffee
  16. 0  commands/app/stop.coffee
  17. 0  commands/app/unalias.coffee
  18. 0  commands/app/uninstall.coffee
  19. 0  commands/app/upgrade.coffee
  20. +9 −0 commands/apps.coffee
  21. 0  commands/create.coffee
  22. +18 −0 commands/login.coffee
  23. +10 −0 commands/logout.coffee
  24. +5 −0 commands/status.coffee
  25. +7 −0 config.json
  26. +0 −8 examples/davster
  27. +0 −35 examples/mynodester.js
  28. +16 −0 lib/api.coffee
  29. +0 −299 lib/app.js
  30. +0 −106 lib/appdomain.js
  31. +0 −40 lib/apps.js
  32. +0 −137 lib/commands.js
  33. +6 −0 lib/config.coffee
  34. +0 −148 lib/config.js
  35. +0 −36 lib/coupon.js
  36. +0 −36 lib/log.js
  37. +0 −187 lib/npm.js
  38. +0 −22 lib/status.js
  39. +0 −235 lib/user.js
  40. +24 −26 package.json
View
4 CHANGELOG.md
@@ -0,0 +1,4 @@
+0.0.1 / November 30, 2011
+==================
+ * Start of the project
+
View
15 LICENSE
@@ -0,0 +1,15 @@
+Copyright (C) 2011 Chris Matthieu (contact info: chris@nodester.com)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, Version 3, 19 November 2007.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see http://www.gnu.org/licenses/agpl-3.0.html.
+
+http://www.gnu.org/licenses/why-affero-gpl.html
View
34 README.md
@@ -1,12 +1,11 @@
-# Nodester API CLI access
+**nodester-cli is a wrapper for the Nodester REST API**
-This app is a little wrapper around the REST API for the [Nodester](http://nodester.com/) OS Node hosting platform.
## Installation
+
+To install nodester-cli, use [npm](http://github.com/isaacs/npm):
-**If you are using `npm 1.0` you need to provide the `-g` flag to install this app globally.**
-
- npm install nodester-cli -g
+ $ npm install -g nodester-cli
## Usage
@@ -14,23 +13,22 @@ This app is a little wrapper around the REST API for the [Nodester](http://nodes
nodester help app
nodester help user
- //All options
nodester help all
+## LICENSE
-## Local installation
-
-If you have your own instance of [Nodester](http://nodester.com/) installed on your own server, the
-command line app is designed to work with that too. Currently it supports 3 environment variables
-to change a couple of default settings.
+Copyright (C) 2011 Chris Matthieu (contact info: chris@nodester.com)
-Here is a simple example:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, Version 3, 19 November 2007.
- #!/bin/bash
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
- export NODESTER_BRAND=davster;
- export NODESTER_APIHOST=auth.davglass.com;
- nodester "$@"
- export NODESTER_BRAND=;
- export NODESTER_APIHOST=;
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see http://www.gnu.org/licenses/agpl-3.0.html.
+http://www.gnu.org/licenses/why-affero-gpl.html
View
36 TODO.md
@@ -0,0 +1,36 @@
+# TODO
+
+### Minor
+
+ * Nothing here yet
+
+### Major
+
+ * Remove all SSH key logic and replace with GitHub integration (maybe)
+ * WebForm for requesting coupons
+ * WebForm for requesting password resets
+ * WebForm for resetting password
+ * WebForm for resetting SSH key for git
+
+ * The following commands:
+ nodester status - Displays service status
+ nodester login <username> <password> - Creates local user file if credentials are valid
+ nodester logout - Deletes local user file
+ nodester apps - Lists all user apps
+
+ nodester create <appname> <(optional initial js file)> - Creates app on server and sets the initial js file. Creates app folder locally
+ nodester <appname> info - Displays app info.
+ nodester <appname> logs - Displays app logs
+ nodester <appname> start - Starts the app
+ nodester <appname> restart - Restarts the app
+ nodester <appname> stop - Stops the app
+ nodester <appname> delete - Deletes the app
+ nodester <appname> push - Pushes files to the app
+ nodester <appname> link <giturl> - Future pushes will pull data from <giturl>
+ nodester <appname> install <package names> - Installs packages for npm
+ nodester <appname> upgrade - Upgrades packages for npm
+ nodester <appname> uninstall <package names> - Uninstalls packages for npm. Package name "all" will clean npm registry
+ nodester <appname> alias <domain-name> - Set up external domain route for app
+ nodester <appname> unalias <domain-name> - Remove external domain route for app
+ nodester <appname> aliases - List all routes
+
View
49 bin/cli.coffee
@@ -0,0 +1,49 @@
+#!/usr/bin/env coffee
+require('coffee-script');
+config = require '../lib/config'
+path = require 'path'
+fs = require 'fs'
+log = require 'node-log'
+log.setName config.service
+
+commando = {}
+commandPath = path.join __dirname, '../commands/'
+
+# Parse process args to command name and command arguments
+parse = ->
+ args = process.argv[2...]
+ command = args[0]
+ args.shift()
+ if commandExists command
+ require(commandPath + command).exe commando, args
+ else if appExists command
+ command = args[0]
+ args.shift()
+ commandPath = path.join __dirname, '../commands/app/'
+ if commandExists command
+ require(commandPath + command).exe commando, args
+ else
+ defaultHelp commandPath, args
+ else
+ defaultHelp commandPath, args
+
+defaultHelp = (commandPath, args) ->
+ if commandExists 'help'
+ require(commandPath + 'help').exe(commando, args)
+ else
+ files = fs.readdirSync commandPath
+ return log.error 'No commands found.' unless files
+ commands = (path.basename(x, path.extname(x)) for x in files)
+ log.info 'Available Commands:'
+ log.info " - #{command}" for command in commands
+
+commandExists = (command) ->
+ try
+ require.resolve path.join commandPath, command
+ return true
+ catch err
+ return false
+
+appExists = (appName) -> appName in config.applications
+
+parse()
View
12 bin/nodester.js
@@ -1,12 +0,0 @@
-#!/usr/bin/env node
-
-process.nodester = {
- brand: 'nodester',
- apihost: 'api.nodester.com'
-}
-
-var cli = require('nodester-cli'),
- command = process.argv[0],
- cmds = cli.commands;
-
-cli.run(cmds, command);
View
0  commands/app/alias.coffee
No changes.
View
0  commands/app/aliases.coffee
No changes.
View
0  commands/app/info.coffee
No changes.
View
0  commands/app/install.coffee
No changes.
View
0  commands/app/link.coffee
No changes.
View
0  commands/app/logs.coffee
No changes.
View
0  commands/app/push.coffee
No changes.
View
0  commands/app/restart.coffee
No changes.
View
0  commands/app/start.coffee
No changes.
View
0  commands/app/stop.coffee
No changes.
View
0  commands/app/unalias.coffee
No changes.
View
0  commands/app/uninstall.coffee
No changes.
View
0  commands/app/upgrade.coffee
No changes.
View
9 commands/apps.coffee
@@ -0,0 +1,9 @@
+log = require 'node-log'
+config = require '../lib/config'
+
+exports.exe = (cmd, args) ->
+ return log.error 'Not logged in' unless config.username? and config.password?
+ if config.applications.length > -1
+ log.info x for x in config.applications
+ else
+ log.error 'No applications.'
View
0  commands/create.coffee
No changes.
View
18 commands/login.coffee
@@ -0,0 +1,18 @@
+log = require 'node-log'
+api = require '../lib/api'
+config = require '../lib/config'
+
+exports.exe = (cmd, args) ->
+ return log.error 'Please logout before trying to login' if config.username? and config.password?
+ return log.error 'Missing arguments' if args.length < 2
+ api.post 'login', {username: args[0], password: args[1]}, (error, response, body) ->
+ return log.error(error) if error
+ parsed = JSON.parse body
+ if parsed.valid
+ config.username = args[0]
+ config.password = args[1]
+ config.applications = parsed.applications
+ config.write()
+ log.info 'Login successful'
+ else
+ log.error parsed.error
View
10 commands/logout.coffee
@@ -0,0 +1,10 @@
+log = require 'node-log'
+config = require '../lib/config'
+
+exports.exe = (cmd, args) ->
+ return log.error 'Not logged in' unless config.username? and config.password?
+ config.username = null
+ config.password = null
+ config.applications = []
+ config.write()
+ log.info 'Logged out'
View
5 commands/status.coffee
@@ -0,0 +1,5 @@
+log = require 'node-log'
+api = require '../lib/api'
+
+exports.exe = (cmd, args) ->
+ api.get 'status', (res) -> log.info "#{x}: #{res[x]}" for x of res
View
7 config.json
@@ -0,0 +1,7 @@
+{
+ "service":"nodester",
+ "host":"nodester.com",
+ "user":null,
+ "password":null,
+ "applications":["testapp"]
+}
View
8 examples/davster
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-export NODESTER_BRAND=davster;
-export NODESTER_APIHOST=auth.davglass.com;
-nodester "$@"
-export NODESTER_BRAND=;
-export NODESTER_APIHOST=;
-
View
35 examples/mynodester.js
@@ -1,35 +0,0 @@
-#!/usr/bin/env node
-
-/**
-* Setup the brand info here..
-*/
-process.nodester = {
- brand: 'myapp',
- apihost: 'nodester.myapp.com'
-}
-
-//Include the CLI
-var cli = require('nodester-cli'),
- //Find the command (process.argv has already been processed here to remove node and scriptname)
- command = process.argv[0],
- //Include the commands so you can add your own
- cmds = cli.commands;
-
-/*
-* Add a new command:
-* mynodester davglass
-* mynodester davglass test
-* mynodester help davglass
-*/
-cmds.davglass = {
- test: function() {
- cli.log.info('DAVGLASS TEST');
- },
- usage: function() {
- cli.log.usage('davglass USAGE GOES HERE');
- }
-}
-
-//Execute the command..
-cli.run(cmds, command);
-
View
16 lib/api.coffee
@@ -0,0 +1,16 @@
+config = require './config'
+request = require 'request'
+log = require 'node-log'
+
+send = (path, method, cb, msg) ->
+ request {url: "http://#{config.host}/#{path}", method: method, json: JSON.stringify msg}, (error, res, body) ->
+ return log.error error if error?
+ return log.error "#{res.statusCode} - Invalid API '#{path}'" if res?.statusCode is 404
+ return log.error "Failed to read response from server." unless body?
+ cb JSON.parse body
+
+module.exports =
+ get: (path, cb) -> send path, 'GET', cb
+ del: (path, cb) -> send path, 'DELETE', cb
+ post: (path, body, cb) -> send path, 'POST', cb, body
+ put: (path, body, cb) -> send path, 'PUT', cb, body
View
299 lib/app.js
@@ -1,299 +0,0 @@
-var node = require('nodester-api').nodester,
- config = require('./config'),
- path = require('path'),
- exists = path.existsSync;
-log = require('./log'), util = require('util'), exec = require('child_process').exec, fs = require('fs');
-
-
-module.exports = {
- usage: function () {
- log.usage('app or <appname> is not required if inside an app directory after you call setup');
- log.usage('app setup <appname> - Configure this app for future app commands');
- log.usage('app info <appname> - Returns app specific information');
- log.usage('app logs <appname> - Returns app logs');
- log.usage('app stop|start|restart <appname> - Controls app status.');
- log.usage('app create <appname> <startfile> - Creates a new app named <appname>, <startfile> is optional.');
- log.usage('app delete <appname> - Deletes the app.');
- log.usage('app gitreset <appname> - Resets the app to git HEAD (in case you want a clean restart).');
- log.usage('app init <appname> - Fetches the remote repo and sets it up.');
- log.usage('app clone <appname> - Fetches the remote repo.');
- },
- setup: function (args) {
- if (!args.length) {
- log.error('appname required');
- return;
- }
- config.writeApp(args[0]);
- },
- info: function (args) {
- config.check();
- var appname = config.appname;
- if (args.length) {
- appname = args[0].toLowerCase();
- }
- log.info('Gathering information about:', appname);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_info(appname, function (err, data, original) {
- if (err) {
- log.error(err.message);
- }
- var l = 'info',
- r = data.running;
- if (data.running == false || data.running.indexOf('error') > -1 || data.running.indexOf('failed-to-stop') > -1) {
- l = 'warn';
- if (r === false) {
- r = 'false'
- }
- r = r.red;
- }
- var pid = '';
- if (data.pid) {
- pid = '(pid: ' + data.pid + ')';
- }
- log[l](appname, 'on port', data.port, 'running:', r.bold, pid);
- log.info('gitrepo:', data.gitrepo);
- log.info('appfile:', data.start);
- });
- },
- logs: function (args) {
- config.check();
- var appname = config.appname;
- if (args.length) {
- appname = args[0].toLowerCase();
- }
-
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_logs(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.lines && data.lines.length && data.lines[0] !== '') {
- log.info('Showing logs for:', appname);
- data.lines.forEach(function (l) {
- log.plain(l);
- });
- } else {
- log.warn('no log data returned.');
- }
- });
-
- },
- stop: function (args) {
- config.check();
- var appname = config.appname;
- if (args.length) {
- appname = args[0].toLowerCase();
- }
- log.info('Attemping to stop app:', appname);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_stop(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.status == "success") {
- log.info('app stopped.');
- } else {
- log.warn(data.status);
- }
- });
- },
- start: function (args) {
- config.check();
- var appname = config.appname;
- if (args.length) {
- appname = args[0].toLowerCase();
- }
- log.info('Attemping to start app:', appname);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_start(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.status == "success") {
- log.info('app started.'.bold.green);
- } else {
- log.warn(data.status);
- }
- });
- },
- restart: function (args) {
- config.check();
- var appname = config.appname;
- if (args.length) {
- appname = args[0].toLowerCase();
- }
- log.info('Attemping to restart app:', appname);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_restart(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.status == "success") {
- log.info('app restarted.'.bold.green);
- } else {
- log.warn(data.status);
- }
- });
- },
- gitreset: function (args) {
- config.check();
- var appname = config.appname;
- if (args.length) {
- var appname = args[0].toLowerCase();
- }
- log.warn('resetting app:', appname);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_gitreset(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.status == "success") {
- log.warn('successfully reset app', appname.bold);
- } else {
- log.info(original);
- log.error(data.status);
- }
- });
- },
- delete: function (args) {
- config.check();
- var appname = config.appname;
- if (args.length) {
- var appname = args[0].toLowerCase();
- }
- log.warn('deleting app:', appname);
- log.warn('Are you sure you want to do this?');
- log.plain(' Waiting 10 seconds before continuing, Ctrl+C to abort)');
- util.print('.');
- var timer = setInterval(function () {
- util.print('.');
- }, 1000);
- setTimeout(function () {
- clearInterval(timer);
- util.print('\n');
- log.warn('Really deleting app now, you were warned..');
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_delete(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.status == "success") {
- log.warn('successfully deleted app', appname.bold);
- } else {
- log.info(original);
- log.error(data.status);
- }
- });
- }, 10000);
- },
- create: function (args) {
- config.check();
- if (!args.length) {
- log.error('appname required');
- return;
- }
- var name = args[0].toLowerCase();
- var start = args[1] || 'server.js';
- log.info('creating app:', name, start);
-
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_create(name, start, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.status == "success") {
- log.info('successfully created app', name.bold, 'to will run on port', ((data.port) + '').bold, 'from', start.bold);
- log.info('run', (config.brand + ' app init ' + name).yellow.bold, 'to setup this app.');
- } else {
- log.info(original);
- log.error(data.status, ':', data.message);
- }
- });
- },
- init: function (args) {
- config.check();
- if (!args.length) {
- log.error('appname required');
- return;
- } else {
- var appname = args[0].toLowerCase();
- var folder = appname;
- if (args[1]) {
- folder = args[1].toLowerCase();
- }
- }
- log.info('initializing git repo for', appname, 'into folder', folder);
- if (!exists(folder)) {
- try {
- fs.mkdirSync(folder, 0750);
- } catch (e) {
- log.error(e.toString());
- }
- }
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_info(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- log.info('cloning the repo', 'git clone ' + data.gitrepo + ' ' + folder);
- var child = exec('git clone ' + data.gitrepo + ' ' + folder, function (error, stdout, stderr) {
- log.info('clone complete');
- var rcfile = config.writeApp(appname, folder);
- log.info('writing app files');
- fs.writeFileSync(folder + '/.gitignore', rcfile + "\n");
-
- var defaultCode = "var http = require('http');\n" + "http.createServer(function (req, res) {\n" + " res.writeHead(200, {'Content-Type': 'text/plain'});\n" + " res.end('Hello World\\nApp (" + appname + ") is running..');\n" + "}).listen(" + data.port + ");\n";
-
- fs.writeFileSync(folder + '/' + data.start, defaultCode);
- var cmd = 'cd ' + folder + '; git add ' + data.start + ' .gitignore; git commit -am "Initial commit via ' + config.brand + '-cli"; git push origin master;';
- log.info('processing the initial commit');
-
- var child2 = exec(cmd, function (error, stdout, stderr) {
- log.info(appname, "started.");
- log.info('Some helpful app commands:\n');
- log.plain(' cd ./' + folder);
- log.plain(' curl http://' + folder + '.nodester.com/');
- log.plain(' ', (config.brand + ' app info').yellow);
- log.plain(' ', (config.brand + ' app logs').yellow);
- log.plain(' ', (config.brand + ' app stop|start|restart').yellow);
- });
- });
- });
- },
- clone: function (args) {
- config.check();
- if (args.length) {
- var appname = folder = args[0].toLowerCase();
- if (args[1]) {
- folder = args[1].toLowerCase();
- }
- }
- log.info('initializing git repo for', appname, 'into folder', folder);
- try {
- fs.mkdirSync(folder, 0750);
- } catch (e) {
- log.error(e.toString());
- }
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.app_info(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- log.info('cloning the repo', 'git clone ' + data.gitrepo + ' ' + folder);
- var child = exec('git clone ' + data.gitrepo + ' ' + folder, function (error, stdout, stderr) {
- var rcfile = config.writeApp(appname, folder);
- fs.writeFileSync(folder + '/.gitignore', rcfile + "\n");
- });
- });
-
- }
-}
View
106 lib/appdomain.js
@@ -1,106 +0,0 @@
-var node = require('nodester-api').nodester,
- config = require('./config'),
- log = require('./log');
-
-
-module.exports = {
- usage: function () {
- log.usage('In a configured app dir, <appname> is optional. (domain aliases appdomain)');
- log.usage('domain add|create <appname> <domainname> - Add a domain router for this app');
- log.usage('domain remove|delete <appname> <domainname> - Remove a domain router from this app');
- log.usage('domain - List domains');
- },
- add: function (args) {
- config.check();
- var appname = config.appname,
- domain;
- if (args.length) {
- if (args.length === 2) {
- domain = args[1];
- appname = args[0];
- } else {
- domain = args[0];
- }
- }
- if (!domain) {
- log.error('<domainname> required');
- } else if (!appname) {
- log.error('<appname> name required');
- }
- log.info('adding domain', domain, 'to', appname);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.appdomain_add(appname, domain, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.status == 'success') {
- log.info(original);
- log.info(data.message);
- log.info('Please restart before any changes will be seen');
- } else {
- log.info(original);
- log.warn(data);
- }
- });
- },
- create: function (args) {
- module.exports.add.call(this, args);
- },
- remove: function (args) {
- module.exports.delete.call(this, args);
- },
- delete: function (args) {
- config.check();
- var appname = config.appname,
- domain;
- if (args.length) {
- if (args.length === 2) {
- domain = args[1];
- appname = args[0];
- } else {
- domain = args[0];
- }
- }
- if (!domain) {
- log.error('<domainname> required');
- } else if (!appname) {
- log.error('<appname> name required');
- }
- log.info('removing domain', domain, 'from', appname);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.appdomain_delete(appname, domain, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.status == 'success') {
- log.info(original);
- log.info(data.message);
- log.info('Please restart before any changes will be seen');
- } else {
- log.info(original);
- log.warn(data);
- }
- });
- },
- run: function () {
- config.check();
- log.info('fetching your list of domain aliases');
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.appdomains(function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err);
- }
- if (data.length > 0) {
- data.forEach(function (i) {
- log.info(i.domain.white, 'aliased to app', i.appname.white, 'running on port', i.port);
- });
- } else {
- log.warn('no app domains to report');
- }
- });
- }
-
-}
View
40 lib/apps.js
@@ -1,40 +0,0 @@
-var node = require('nodester-api').nodester,
- config = require('./config'),
- log = require('./log');
-
-
-module.exports = {
- usage: function () {
- log.usage('apps list - list all your registered apps');
- },
- run: function () {
- //Placeholder for later adding more `cmd apps` commands
- this.list();
- },
- list: function (args) {
- config.check();
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.apps_list(function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err);
- }
- if (data.length > 0) {
- for (var i in data) {
- var l = 'info',
- r = data[i].running;
- if (data[i].running == false || data[i].running == 'false' || data[i].running.indexOf('error') > -1 || data[i].running.indexOf('failed-to') > -1) {
- l = 'warn';
- if (r === false || r == 'false') {
- r = 'false'
- }
- r = r.red;
- }
- log[l](data[i].name, 'on port', data[i].port, 'running:', r.bold);
- }
- } else {
- log.warn('no apps to report');
- }
- });
- }
-}
View
137 lib/commands.js
@@ -1,137 +0,0 @@
-var log = require('./log');
- brand = "nodester",
- apihost = "api.nodester.com",
- apisecure = false,
- env = process.env,
- fs = require('fs');
-
-
-
-process.argv = process.argv.slice(2);
-
-if (env.NODESTER_APIHOST) {
- apihost = env.NODESTER_APIHOST;
-}
-if (env.NODESTER_APISECURE) {
- apisecure = true;
-}
-if (env.NODESTER_BRAND) {
- brand = env.NODESTER_BRAND;
-}
-
-
-var nodester_config = {
- apisecure: apisecure,
- apihost: apihost,
- brand: brand,
- appname: '',
- config: {
- username: '',
- password: ''
- }
-};
-if (!process.nodester) {
- process.nodester = {};
-}
-for (var i in nodester_config) {
- if (!process.nodester[i]) {
- process.nodester[i] = nodester_config[i];
- }
-}
-
-var path = require('path');
-try {
-var pack = JSON.parse(fs.readFileSync(path.join(__dirname, '../', 'package.json'), encoding='utf8'));
-} catch (e) {
- var pack = {
- version: 'unknown'
- };
-}
-
-require('./config').parse();
-
-exports.log = log;
-
-exports.commands = {
- status: require('./status'),
- coupon: require('./coupon'),
- apps: require('./apps'),
- app: require('./app'),
- user: require('./user'),
- appdomain: require('./appdomain'),
- domain: require('./appdomain'),
- npm: require('./npm'),
- appnpm: require('./npm'),
- version: {
- run: function() {
- log.plain(pack.version);
- }
- },
- help: {
- run: function(args) {
- if (args[0] && args[0].toLowerCase() === 'all') {
- showUsage();
- } else {
- showHelp(args);
- }
- }
- }
-};
-
-exports.commands.v = exports.commands.version;
-exports.commands['-v'] = exports.commands.version;
-exports.commands['-version'] = exports.commands.version;
-exports.commands['--version'] = exports.commands.version;
-
-exports.run = function(cmds, command) {
- if (!command) {
- showHelp(exports.commands);
- process.exit(1);
- }
-
- if (!cmds[command] && process.nodester.appname) {
- command = 'app';
- process.argv.unshift('app');
- }
-
- if (cmds[command]) {
- if (cmds[command][process.argv.slice(1)[0]]) {
- cmds[command][process.argv.slice(1)[0]](process.argv.slice(2));
- } else if (cmds[command].run) {
- cmds[command].run(process.argv.slice(1));
- } else {
- if (cmds[command].usage) {
- cmds[command].usage();
- }
- }
- } else {
- log.error('command not found: ' + command);
- }
-}
-
-
-var showHelp = exports.showHelp = function(args) {
- var cmds = exports.commands;
- if (args && cmds[args[0]] && cmds[args[0]].usage) {
- cmds[args[0]].usage();
- } else {
- log.info('showing all available sub commands');
- for (var i in cmds) {
- if (cmds[i].usage) {
- log.usage(i);
- }
- }
- log.info('For more help, type', brand, 'help <command>');
- }
-}
-
-var showUsage = function () {
- log.info('show usage');
- var cmds = exports.commands;
- for (var i in cmds) {
- if (cmds[i].usage) {
- cmds[i].usage();
- }
- }
-};
-
View
6 lib/config.coffee
@@ -0,0 +1,6 @@
+path = require 'path'
+fs = require 'fs'
+
+loc = path.join __dirname, '../config.json'
+module.exports = config = JSON.parse fs.readFileSync loc
+module.exports.write = -> fs.writeFileSync loc, JSON.stringify config
View
148 lib/config.js
@@ -1,148 +0,0 @@
-
-var path = require('path'),
- fs = require('fs'),
- path = require('path'),
- exists = path.existsSync,
- crypto = require("crypto"),
- iniparser = require('iniparser'),
- log = require('./log');
-
-
-exports.check = function() {
- //log.info('Checking config..');
- if (process.nodester.config.username == "" || process.nodester.config.password == "") {
- log.error("Username and password not set in config.\nPlease run " + process.nodester.brand + " user setup <username> <password>\n");
- }
- //log.info('Config valid..');
-}
-
-exports.__defineGetter__('username', function() {
- return process.nodester.config.username;
-});
-exports.__defineGetter__('password', function() {
- return process.nodester.config.password;
-});
-exports.__defineGetter__('apihost', function() {
- return process.nodester.apihost;
-});
-exports.__defineGetter__('apisecure', function() {
- return process.nodester.apisecure;
-});
-exports.__defineGetter__('brand', function() {
- return process.nodester.brand;
-});
-exports.__defineGetter__('appname', function() {
- return process.nodester.appname.toLowerCase();
-});
-
-exports.writeUser = function(user, pass) {
- log.info('writing user data to config');
- var config_file = path.join(process.env.HOME, "." + process.nodester.brand + '.rc');
- var str = user + ':' + pass;
- var x = cryptAuth(str);
- var out = 'auth=' + x + '\n';
- fs.writeFileSync(config_file, out, encoding='utf8');
- return config_file;
-}
-
-exports.writeApp = function(appname, folder) {
- if (!folder) {
- folder = '';
- }
- if(!exists(folder)){
- fs.mkdirSync(folder, '0777');
- }
- var config_file = path.join("./" + folder, "." + process.nodester.brand + ".appconfig");
- log.info('Writing app data to config in ' + config_file);
- fs.writeFileSync(config_file, "appname=" + appname.toLowerCase() + "\n");
- return "." + process.nodester.brand + ".appconfig";
-}
-
-var getKey = function(warn) {
- var ssh = path.join(process.env.HOME, ".ssh"),
- data = '',
- keys = [
- path.join(ssh, "id_dsa"),
- path.join(ssh, "id_rsa"),
- path.join(ssh, "identity")
- ];
- keys.some(function(v) {
- if (exists(v)) {
- data = fs.readFileSync(v, encoding='utf8') + '';
- return true;
- }
- });
- if (data === '' && warn) {
- log.warn('No key file found, encrypt is not going to be strong.');
- }
-
- return data;
-}
-
-
-var convertConfig = function(config_file) {
- var config = iniparser.parseSync(config_file);
- var str = config.username + ':' + config.password;
- var x = cryptAuth(str);
- var new_config_file = path.join(process.env.HOME, "." + process.nodester.brand + '.rc');
- var out = 'auth=' + x + '\n';
- fs.writeFileSync(new_config_file, out, encoding='utf8');
- log.warn('saved new config file: ' + new_config_file);
- log.warn('removing old config file');
- fs.unlinkSync(config_file);
-};
-
-/**
-* Based heavily on NPM's _authCrypt
-* https://github.com/isaacs/npm/blob/master/lib/utils/ini.js
-*/
-
-var decryptAuth = function(str) {
- if (crypto.Decipher) {
- var key = getKey();
- var c = (new crypto.Decipher).init("aes192", key)
- var auth = c.update(str, "hex", "utf8")
- auth += c.final("utf8");
- } else {
- auth = str;
- }
-
- var b = new Buffer(auth, 'base64');
- return b.toString('utf8');
-}
-
-var cryptAuth = function(str) {
- str = new Buffer(str).toString('base64');
- if (crypto.Cipher) {
- var key = getKey(true);
- var c = (new crypto.Cipher).init("aes192", key)
- var Crypt = c.update(str, "utf8", "hex");
- Crypt += c.final("hex");
- } else {
- Crypt = str;
- }
- return Crypt;
-}
-
-exports.parse = function() {
- //log.info('parsing config');
- var old_config_file = path.join(process.env.HOME, "." + process.nodester.brand + "rc");
- if (exists(old_config_file)) {
- log.warn('old config file found, converting..');
- convertConfig(old_config_file);
- }
-
- var config_file = path.join(process.env.HOME, "." + process.nodester.brand + '.rc');
- if (exists(config_file)) {
- var config = iniparser.parseSync(config_file);
- var a = decryptAuth(config.auth).split(':');
- process.nodester.config.username = a[0];
- process.nodester.config.password = a[1];
- }
-
- var apprcfile = "." + process.nodester.brand + ".appconfig";
- if (exists(apprcfile)) {
- var config = iniparser.parseSync(apprcfile);
- process.nodester.appname = config.appname.toLowerCase();
- }
-}
View
36 lib/coupon.js
@@ -1,36 +0,0 @@
-var node = require('nodester-api').nodester,
- config = require('./config'),
- log = require('./log');
-
-
-module.exports = {
- usage: function () {
- log.usage('coupon <email address> - Request a coupon code for access');
- },
- run: function (args) {
- if (!args.length) {
- //log.error('Email address is required..');
- this.usage();
- return;
- }
- var email = args[0];
- log.info('Requesting coupon code for: ' + email);
- var nodeapi = new node("", "", process.nodester.apihost, config.apisecure);
-
- nodeapi.coupon_request(email, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err);
- }
- var s = data.status;
- if (s.indexOf('success') === 0) {
- s = s.replace('success', '');
- log.info('SUCCESS'.green.bold + s);
- } else {
- log.info(original);
- log.info(data.status);
- }
- });
-
- }
-}
View
36 lib/log.js
@@ -1,36 +0,0 @@
-require('colors');
-
-var level = process.env.NODESTER_LOGLEVEL || 0;
-
-var strArgs = function (args) {
- if (args.length > 1) {
- var str = [];
- for (var i in args) {
- str.push(args[i]);
- }
- return str.join(' ');
- } else {
- return args[0];
- }
- }
-
-exports.plain = function () {
- console.log(strArgs(arguments));
-}
-
-exports.usage = function () {
- console.log(process.nodester.brand.magenta, strArgs(arguments));
-}
-
-exports.info = function () {
- console.log(process.nodester.brand.magenta, 'info'.white, strArgs(arguments));
-}
-
-exports.warn = function (str) {
- console.log(process.nodester.brand.magenta, 'warn'.yellow, strArgs(arguments));
-}
-
-exports.error = function (str) {
- console.log(process.nodester.brand.magenta, 'ERROR'.red.inverse, strArgs(arguments));
- process.exit(1);
-}
View
187 lib/npm.js
@@ -1,187 +0,0 @@
-var node = require('nodester-api').nodester,
- path = require('path'),
- fs = require('fs'),
- exists = path.existsSync,
- config = require('./config'),
- log = require('./log');
-
-
-module.exports = {
- usage: function () {
- log.usage('In a configured app dir, <appname> is optional.');
- log.usage('All arguments after install|update|uninstall or appname will be sent to npm as packages.');
- log.usage('npm list - Lists the installed npm packages for this app.');
- log.usage('npm install <appname> <packages> - Installs the list of specified packages to this app.');
- log.usage('npm update <appname> <packages> - Update the list of specified packages to this app.');
- log.usage('npm uninstall <appname> <packages> - Removes the list of specified packages to this app.');
- },
- install: function (args) {
- config.check();
- var appname = config.appname,
- p = args;
-
- if (args.length && !appname) {
- appname = args[0];
- p = args.splice(1);
- }
- if (!p.length) {
- if (exists('package.json')) {
- log.info('grabbing dependencies from package.json...');
- var depen = JSON.parse(fs.readFileSync('package.json')).dependencies;
- if (!depen) {
- log.error('no depedencies found!');
- } else {
- p = [];
- for (dependency in depen) {
- p.push(dependency);
- }
- }
- } else {
- log.error('no packages to install!');
- }
- }
- log.info('installing to app:', appname);
- log.info('installing these npm packages:', p);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.appnpm_install(appname, p.join(' '), function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.output) {
- var out = data.output.split('\n');
- out.forEach(function (l) {
- if (l.indexOf('stdout: ') === -1) {
- if (l.length > 1) {
- l = l.replace('stderr: ', '');
- l = l.split(' ');
- l[0] = l[0].magenta;
- if (l[1]) {
- if (l[1].toLowerCase() === 'warn') {
- l[1] = l[1].red;
- } else if (l[1].toLowerCase() === 'erro') {
- l[1] = l[1].red.inverse.bold;
- } else {
- l[1] = l[1].white;
- }
- }
- log.usage(l.join(' '));
- }
- }
- });
- }
- log.plain('');
- log.warn('you should restart your app after you are finished installing packages.'.yellow.bold);
- });
- },
- list: function (args) {
- config.check();
- var appname = config.appname;
- if (args.length && !appname) {
- appname = args[0];
- }
- log.info('list npm packages for app:', appname);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.appnpm_list(appname, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.output) {
- var out = data.output.split('\n');
- out.forEach(function (l) {
- if (l.indexOf('stdout: ') === -1) {
- if (l.length > 1) {
- l = l.replace('stderr: ', '');
- l = l.split(' ');
- l[0] = l[0].magenta;
- if (l[1]) {
- l[1] = l[1].white;
- }
- log.usage(l.join(' '));
- }
- }
- });
- }
- log.plain('');
- });
- },
- update: function (args) {
- config.check();
- var appname = config.appname,
- p = args;
-
- if (args.length && !appname) {
- appname = args[0];
- p = args.splice(1);
- }
- if (!p.length) {
- log.error('no packages to install');
- }
- log.info('updating to app:', appname);
- log.info('updating these npm packages:', p);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.appnpm_update(appname, p.join(' '), function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.output) {
- var out = data.output.split('\n');
- out.forEach(function (l) {
- if (l.indexOf('stdout: ') === -1) {
- if (l.length > 1) {
- l = l.replace('stderr: ', '');
- l = l.split(' ');
- l[0] = l[0].magenta;
- if (l[1]) {
- l[1] = l[1].white;
- }
- log.usage(l.join(' '));
- }
- }
- });
- }
- log.plain('');
- log.warn('you should restart your app after you are finished installing packages.'.yellow.bold);
- });
- },
- uninstall: function (args) {
- config.check();
- var appname = config.appname,
- p = args;
-
- if (args.length && !appname) {
- appname = args[0];
- p = args.splice(1);
- }
- if (!p.length) {
- log.error('no packages to install');
- }
- log.info('removing to app:', appname);
- log.info('removing these npm packages:', p);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.appnpm_uninstall(appname, p.join(' '), function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- if (data.output) {
- var out = data.output.split('\n');
- out.forEach(function (l) {
- if (l.indexOf('stdout: ') === -1) {
- if (l.length > 1) {
- l = l.replace('stderr: ', '');
- l = l.split(' ');
- l[0] = l[0].magenta;
- if (l[1]) {
- l[1] = l[1].white;
- }
- log.usage(l.join(' '));
- }
- }
- });
- }
- });
- }
-}
View
22 lib/status.js
@@ -1,22 +0,0 @@
-var node = require('nodester-api').nodester,
- config = require('./config'),
- log = require('./log');
-
-
-module.exports = {
- usage: function () {
- log.usage('status - Show', config.brand, 'API status');
- },
- run: function () {
- log.info('checking api status for:', config.apihost);
- var nodeapi = new node('', '', config.apihost, config.apisecure);
- nodeapi.status(function (err, data, original) {
- if (err) {
- log.info(original);
- }
- for (var i in data) {
- log.info(i, data[i].toString().bold);
- }
- });
- }
-}
View
235 lib/user.js
@@ -1,235 +0,0 @@
-var node = require('nodester-api').nodester,
- config = require('./config'),
- sys = require('sys'),
- path = require('path'),
- log = require('./log'),
- fs = require('fs'),
- tty, iniparser = require('iniparser');
-
-try {
- tty = require('tty');
-} catch (e) {}
-
-
-var info = {
- email: '',
- coupon: '',
- username: '',
- sshkey: ''
-};
-
-module.exports = {
- usage: function () {
- log.usage('user register <coupon-code> - Register a user');
- log.usage('user setup <username> <password> - Setup this user');
- log.usage('user setpass sendtoken - Sends password reset token to user email');
- log.usage('user setpass <token> <new_password> - Set a new password for this user');
- log.usage('user setkey </path/to/sshkey> - Set an sshkey (if no argument, ~/.ssh/id_rsa.pub is used)');
- log.usage('user create <username> <password> <email address> <file containing ssh public key> <coupon code> - Create a user');
- },
- create: function (args) {
- if (args.length < 5) {
- log.usage('user create <username> <password> <email address> <file containing ssh public key> <coupon code> - Create a user');
- log.error('All arguments are required');
- }
-
- var user = args[0];
- var pass = args[1];
- var email = args[2];
- var rsakey = args[3];
- var coupon = args[4];
-
- log.info('creating user:', user, ' <' + email + '>');
- var nodeapi = new node("", "", config.apihost, config.apisecure);
- args.push(function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- log.info('user successfully created');
- config.writeUser(user, pass);
- });
- nodeapi.user_create.apply(nodeapi, args);
- },
- setkey: function (args) {
- config.check();
- var key = args[0];
- if (!key) {
- key = path.join(process.env.HOME, '.ssh', 'id_rsa.pub');
- }
- if (!path.existsSync(key)) {
- log.error('sshkey was not found:', key);
- }
- var rsadata = fs.readFileSync(key).toString();
- if (rsadata.length < 40) {
- log.error("Invalid SSH key file.");
- }
- log.info('sending sshkey:', key);
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- nodeapi.user_setkey(rsadata, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- log.info('ssh key successfully sent');
- });
- },
- setpass: function (args) {
- config.check();
- var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
- if (args.length == 1 && args[0] == 'sendtoken') {
- nodeapi.user_sendtoken(config.username, function (err, data, original) {
- if (err && !data) {
- log.info(original);
- log.error(err.message);
- } else {
- log.info(data.status);
- log.info('token for setpass has been sent to your email!');
- }
- });
- } else if (args.length == 2) {
- nodeapi.user_setpass(args[0], args[1], function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- log.info('password successfully changed.');
- config.writeUser(config.username, args[0]);
- });
- } else {
- log.error('Argument missing: ', 'setpass sendtoken or setpass <token> <new_password>');
- }
- },
- setup: function (args) {
- if (args.length < 2) {
- log.error('Argument missing: ', '<username> <password>');
- }
- var nodeapi = new node(args[0], args[1], config.apihost, config.apisecure);
- log.info('verifying credentials');
- nodeapi.apps_list(function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- log.info('user verified..');
- config.writeUser(args[0], args[1]);
- });
- },
- register: function (args) {
- if (!args.length) {
- log.error('Coupon Code Required');
- }
- if (args[1] && args[1].indexOf('@') > -1) {
- info.email = args[1];
- }
- if (!info.email && path.existsSync(path.join(process.env.HOME, '.gitconfig'))) {
- var git = iniparser.parseSync(path.join(process.env.HOME, '.gitconfig'));
- info.email = git.user.email;
- } else if (!info.email) {
- log.error('Could not find an email address as an argument or from your ~/.gitconfig, please pass one as an additional argument');
- }
- info.coupon = args[0];
- info.username = process.env.USER;
- var sshkey = path.join(process.env.HOME, '.ssh', 'id_rsa.pub')
- if (path.existsSync(sshkey)) {
- info.sshkey = sshkey;
- } else {
- log.error('Could not auto find your ssh key: ', sshkey, 'use <' + config.brand + ' user create> instead');
- }
- log.info('Registering with the following information:');
- for (var i in info) {
- log.info(i + ':', info[i]);
- }
- log.warn('Does this information look correct? [y/N]');
- log.info('(If it does not, hit Ctrl+C and use <' + config.brand + ' user create> instead)');
- var stdin = process.openStdin();
- stdin.setEncoding('utf8');
- stdin.addListener('data', function (data) {
- stdin.removeAllListeners('data');
- data = data.replace('\n', '').toLowerCase().substring(0, 1);
- if (data === 'y') {
- askPass(function (password) {
- info.password = password;
- log.info('creating user:', info.username, ' <' + info.email + '>');
- var nodeapi = new node("", "", config.apihost, config.apisecure);
- nodeapi.user_create(info.username, info.password, info.email, info.sshkey, info.coupon, function (err, data, original) {
- if (err) {
- log.info(original);
- log.error(err.message);
- }
- log.info('user created..');
- config.writeUser(info.username, info.password);
- });
- });
- } else {
- log.error('aborting registration');
- stdin.pause();
- }
- });
-
- }
-}
-
-var askPass = exports.askPass = function (fn) {
- var stdin = process.openStdin();
- stdin.setEncoding('utf8');
- var p = [],
- c = '';
- console.log('Please enter your password:');
- if (!tty) {
- log.warn('Node version (' + process.version + ') has no tty module, passwords will be echoed to stdout');
- stdin.addListener('data', function (data) {
- data += '';
- data = data.replace('\n', '');
- p.push(data);
- if (p.length === 2) {
- if (p[0] !== p[1]) {
- p = [];
- log.warn('Passwords did not match, please try again.');
- console.log('Please re-enter your password:');
- } else {
- stdin.removeAllListeners('data');
- stdin.pause();
- fn(p[0]);
- }
- } else {
- console.log('Confirm password:');
- }
- });
- } else {
- tty.setRawMode();
- stdin.addListener('data', function (data) {
- data += '';
- switch (data) {
- case '\u0003':
- log.error('exiting from Ctrl+C');
- process.exit()
- break
- case '\n':
- case '\r':
- p.push(c);
- c = '';
- if (p.length === 1) {
- console.log('\nConfirm password:');
- } else {
- if (p[0] === p[1]) {
- stdin.removeAllListeners('data');
- console.log('\n');
- tty.setRawMode(false);
- stdin.pause();
- fn(p[0]);
- } else {
- p = [];
- console.log('\n');
- log.warn('Passwords did not match, please try again.');
- console.log('Please re-enter your password:');
- }
- }
- break;
- default:
- process.stdout.write("*");
- c += data;
- }
- });
- }
- }
View
50 package.json
@@ -1,28 +1,26 @@
{
- "name": "nodester-cli",
- "description": "A CLI tool to allow interaction with the http://nodester.com/ platform.",
- "version": "0.2.34",
- "homepage": "http://nodester.com/",
- "repository": "git://github.com/nodester/nodester-cli.git",
- "author": "Daniel Bartlett <dan@f-box.org> (http://danb-uk.net/)",
- "contributors": [
- "Dav Glass <davglass@gmail.com> @davglass",
- "Chris Matthieu <chris@matthieu.us>",
- "Abraham Williams <4braham@gmail.com>",
- "Contra <contra@australia.edu>",
- "Marcos Oliveira <marcosvm@gmail.com"
- ],
- "preferGlobal" : "true",
- "bin": {
- "nodester": "bin/nodester.js"
- },
- "main": "./lib/commands.js",
- "engines": {
- "node": "*"
- },
- "dependencies" : {
- "nodester-api": ">= 0.1.14",
- "colors": "0.3.0",
- "iniparser": "1.0.1"
- }
+ "name":"nodester-cli",
+ "description":"A CLI tool to allow interaction with the Nodester platform.",
+ "version":"0.3.0",
+ "homepage":"http://github.com/nodester/nodester-cli",
+ "repository":"git://github.com/nodester/nodester-cli.git",
+ "author":"Fractal <contact@wearefractal.com> (http://wearefractal.com/)",
+ "preferGlobal":"true",
+ "bin":{
+ "nodester":"./bin/cli.coffee"
+ },
+ "dependencies":{
+ "coffee-script":"*",
+ "node-log":"*",
+ "request":"*"
+ },
+ "engines":{
+ "node":">= 0.4.0"
+ },
+ "licenses":[
+ {
+ "type":"GPL Affero",
+ "url":"http://github.com/nodester/nodester-cli/raw/master/LICENSE"
+ }
+ ]
}

No commit comments for this range

Something went wrong with that request. Please try again.