Permalink
Browse files

Initial Commit Thrust v0.0.1

  • Loading branch information...
0 parents commit 15f1ab8d7be7a726794c005bdfd25e8c7bfe65e4 @spolu spolu committed Oct 10, 2014
Showing with 1,218 additions and 0 deletions.
  1. +20 −0 LICENSE
  2. +13 −0 index.js
  3. +158 −0 lib/api.base.js
  4. +194 −0 lib/api.js
  5. +98 −0 lib/api.menu.js
  6. +59 −0 lib/api.session.js
  7. +117 −0 lib/api.shell.js
  8. +316 −0 lib/common.js
  9. +93 −0 lib/thrust.js
  10. +20 −0 package.json
  11. +16 −0 test.html
  12. +114 −0 test.js
@@ -0,0 +1,20 @@
+Copyright (c) 2014 Stanislas Polu. All rights reserved.
+
+The MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,13 @@
+/*
+ * node-thrust: index.js
+ *
+ * Copyright (c) 2014, Stanislas Polu. All rights reserved.
+ *
+ * @author: spolu
+ *
+ * @log:
+ * - 2014-10-09 spolu Creation
+ */
+"use strict"
+
+module.exports = require('./lib/thurst.js').thurst({}).spawn;
@@ -0,0 +1,158 @@
+/*
+ * node-thrust: api.base.js
+ *
+ * Copyright (c) 2014, Stanislas Polu. All rights reserved.
+ *
+ * @author: spolu
+ *
+ * @log:
+ * - 2014-10-10 spolu Creation
+ */
+"use strict"
+
+var common = require('./common.js');
+
+var async = require('async');
+var events = require('events');
+
+// ## base
+//
+// Base object representation. Implements creation and base method call as well
+// as event emition and remote method call functionalities.
+//
+// ```
+// @spec { api, type, args }
+// @inherits events.EventEmitter
+// ```
+var base = function(spec, my) {
+ var _super = {};
+ my = my || {};
+ spec = spec || {};
+
+ my.type = spec.type || 'INVALID_TYPE';
+ my.api = spec.api;
+
+ my.target = null;
+ my.create_error = null;
+
+ //
+ // #### _protected_
+ //
+ var pre; /* pre(cb_); */
+ var call; /* call(method, args, cb_); */
+ var invoke; /* invoke(method, args, cb_); */
+ var create; /* create(); */
+
+
+ //
+ // #### _that_
+ //
+ var that = new events.EventEmitter();
+
+ /****************************************************************************/
+ /* PROTECTED METHODS */
+ /****************************************************************************/
+ // ### pre
+ //
+ // Function called before method invokation to ensure the object is fully
+ // constructed
+ // ```
+ // @cb_ {function(err)}
+ // ```
+ pre = function(cb_) {
+ if(my.create_error) {
+ return cb_(err);
+ }
+ else if(!my.target) {
+ that.on('_ready', function() {
+ return cb_();
+ });
+ }
+ else {
+ return cb_();
+ }
+ };
+
+ // ### call
+ //
+ // Call a remote method
+ // ```
+ // @method {string} the method name
+ // @args {object} the argument object
+ // @cb_ {function(err, res)} the callback function
+ // ```
+ call = function(method, args, cb_) {
+ pre(function(err) {
+ if(err) {
+ return cb_(err);
+ }
+ my.api.perform({
+ _id: my.api.action_id(),
+ _action: "call",
+ _target: my.target,
+ _method: method,
+ _args: args || {}
+ }, cb_);
+ });
+ };
+
+ // ### invoke
+ //
+ // Invokes a local method on the object if it exists. Any object inheriting
+ // this base object is supposed to imeplement all remote method.
+ // ```
+ // @method {string} the method name
+ // @args {object} the arguments object
+ // @cb_ {function(err, res)} the callback function
+ // ```
+ invoke = function(method, args, cb_) {
+ pre(function(err) {
+ if(err) {
+ return cb_(err);
+ }
+ else if(!that[method]) {
+ return cb_(common.err('Method not found [' my.type + ']: ' + method,
+ 'thrust:method_not_found'));
+ }
+ else {
+ return that[method](args, cb_);
+ }
+ });
+ };
+
+ // ### create
+ //
+ // Creation method called at construction
+ // ```
+ // @args {object} args object passed from spec
+ // ```
+ create = function(args) {
+ my.api.perform({
+ _id: my.api.action_id(),
+ _action: 'create',
+ _type: my.type,
+ _args: spec.args
+ }, function(err, res) {
+ if(err) {
+ my.create_error = err;
+ }
+ else {
+ my.target = res._target;
+ that.emit('_ready');
+ }
+ });
+ };
+
+ create(spec.args);
+
+ common.method(that, 'pre', pre, _super);
+ common.method(that, 'call', call, _super);
+ common.method(that, 'invoke', invoke, _super);
+ common.method(that, 'create', create, _super);
+
+ common.getter(that, 'target', my, 'target');
+
+ return that;
+}
+
+exports.base = base;
@@ -0,0 +1,194 @@
+/*
+ * node-thrust: api.js
+ *
+ * Copyright (c) 2014, Stanislas Polu. All rights reserved.
+ *
+ * @author: spolu
+ *
+ * @log:
+ * - 2014-10-09 spolu Creation
+ * - 2014-10-10 spolu Event support
+ */
+"use strict"
+
+var common = require('./common.js');
+
+var async = require('async');
+var path = require('path');
+var os = require('os');
+var net = require('net');
+var events = require('events');
+
+
+// ## api
+//
+// Object in charge of RPC with the wrapper process as well as exposing the
+// api components.
+//
+// ```
+// @spec {}
+// @inherits events.EventEmitter
+// ```
+var api = function(spec, my) {
+ var _super = {};
+ my = my || {};
+ spec = spec || {};
+
+ my.salt = Date.now().toString();
+ my.next_id = 0;
+
+ my.BOUNDARY = "--(Foo)++__EXO_SHELL_BOUNDARY__++(Bar)--";
+ my.ACTION_TIMEOUT = 500;
+ my.action_id = 0;
+
+ my.client = null;
+ my.actions = {};
+ my.acc = '';
+
+ if (os.platform() === 'win32') {
+ my.thrust_sock = '\\\\.\\pipe\\thrust.' + uid() + '.sock';
+ }
+ else {
+ my.thrust_sock = path.join(os.tmpdir(),
+ 'thrust.' + uid() + '.sock');
+ }
+ /* TODO(spolu): Remove temporary solution */
+ my.thrust_sock = '/tmp/_exo_shell.sock';
+
+
+ //
+ // #### _public_
+ //
+ var init; /* init(cb_); */
+
+ //
+ // #### _protected_
+ //
+ var uid; /* uid(); */
+ var perform; /* peform(action, cb_); */
+
+ //
+ // #### _private_
+ //
+ var client_data_handler; /* client_data_handler(data); */
+
+ //
+ // #### _that_
+ //
+ var that = new events.EventEmitter();
+
+ /****************************************************************************/
+ /* PRIVATE HELPERS */
+ /****************************************************************************/
+ // ### client_data_handler
+ //
+ // Handles data coming from the client to the shell
+ // ```
+ // @chunk {Buffer} the incoming chunk
+ // ```
+ client_data_handler = function(chunk) {
+ my.acc += chunk;
+ var splits = my.acc.split(my.BOUNDARY);
+ if(splits.length > 0) {
+ var data = splits.shift();
+ my.acc = splits.join(my.BOUNDARY);
+ if(data && data.length > 0) {
+ try {
+ var action = JSON.parse(data);
+ if(action._action === 'reply' && my.actions[action._id.toString()]) {
+ /* my.actions is cleaned up by tcalling the callback. */
+ var cb_ = my.actions[action._id.toString()];
+ if(action._error) {
+ return cb_(common.err(action._error,
+ 'thrust:shell_error'));
+ }
+ return cb_(null, action._result);
+ }
+ }
+ catch(err) {
+ common.log.error(common.err('Parsing error',
+ 'thrust:parsing_error'));
+ common.log.out('=========================================');
+ common.log.out(data);
+ common.log.out('=========================================');
+ }
+ }
+ }
+ };
+
+ /****************************************************************************/
+ /* PROTECTED HELPERS */
+ /****************************************************************************/
+ // ### uid
+ //
+ // Returns a new unique id
+ uid = function() {
+ return my.salt + '-' + (++my.next_id);
+ };
+
+ // ### action_id
+ //
+ // Returns the next action_id
+ action_id = function() {
+ return ++my.action_id;
+ };
+
+ // ### perform
+ //
+ // Performs an action by sending it over the network and storing the callback
+ // for later execution on action response.
+ // ```
+ // @action {object} a valid action object
+ // @cb_ {function(err, res)}
+ // ```
+ perform = function(action, cb_) {
+ var itv = setTimeout(function() {
+ delete my.actions[action._id.toString()];
+ return cb_(common.err('Action timed out: ' + action._id,
+ 'thrust:action_timeout'));
+ }, my.ACTION_TIMEOUT);
+ my.actions[action._id.toString()] = function(err, res) {
+ delete my.actions[action._id.toString()];
+ clearTimeout(itv);
+ return cb_(err, res);
+ };
+ client.write(JSON.stringify(action) + "\n" + BOUNDARY);
+ };
+
+ /****************************************************************************/
+ /* PUBLIC METHODS */
+ /****************************************************************************/
+ // ### init
+ //
+ // Initializes the API and opens the JSON RPC channel
+ // ```
+ // @cb_ {function(err, api)}
+ // ```
+ init = function(cb_) {
+ var now = Date.now();
+
+ my.client = net.connect({ path: my.thrust_sock }, function(err) {
+ if(err) {
+ return cb_(err);
+ }
+ return cb_(null, that);
+ });
+ my.client.on('data', client_data_handler);
+
+ that.shell = require('./api.shell.js').shell;
+ that.session = require('./api.shell.js').session;
+ that.menu = require('./api.shell.js').menu;
+ };
+
+ common.getter(that, 'thrust_sock', my, 'thrust_sock');
+
+ common.method(that, 'uid', uid, _super);
+ common.method(that, 'action_id', action_id, _super);
+ common.method(that, 'perform', perform, _super);
+
+ common.method(that, 'init', init, _super);
+
+ return that;
+}
+
+exports.api = api;
Oops, something went wrong.

0 comments on commit 15f1ab8

Please sign in to comment.