Comparing version 0.4.0 to 0.5.0
@@ -18,12 +18,12 @@ // Generated by LiveScript 1.4.0 | ||
} | ||
prototype.handleRequest = function(arg$){ | ||
var command, replyingTo, payload; | ||
command = arg$.command, replyingTo = arg$.replyingTo, payload = arg$.payload; | ||
prototype.handleRequest = function(arg$, methods){ | ||
var command, responseTo, payload; | ||
command = arg$.command, responseTo = arg$.responseTo, payload = arg$.payload; | ||
switch (false) { | ||
case !this.replyHandlers.hasHandler(replyingTo): | ||
return this.replyHandlers.handle(replyingTo, payload); | ||
case !this.replyHandlers.hasHandler(responseTo): | ||
return this.replyHandlers.handle(responseTo, payload); | ||
case !this.commandHandlers.hasHandler(command): | ||
return this.commandHandlers.handle(command, payload); | ||
return this.commandHandlers.handle(command, payload, methods); | ||
default: | ||
return debug("no handler found for command '" + command + "' and request-id '" + replyingTo + "'"); | ||
return debug("no handler found for command '" + command + "' and request-id '" + responseTo + "'"); | ||
} | ||
@@ -30,0 +30,0 @@ }; |
// Generated by LiveScript 1.4.0 | ||
(function(){ | ||
var uuid, request, debug, CommandSender; | ||
var isEmpty, uuid, request, debug, CommandSender; | ||
isEmpty = require('lodash.isempty'); | ||
uuid = require('node-uuid'); | ||
@@ -14,23 +15,47 @@ request = require('request'); | ||
: {}).exocommPort; | ||
this.lastSentRequestId = null; | ||
} | ||
prototype.send = function(obj){ | ||
var options; | ||
debug("sending command '" + obj.command + "'"); | ||
options = { | ||
prototype.replyMethodFor = function(requestId){ | ||
var this$ = this; | ||
switch (false) { | ||
case !!requestId: | ||
throw new Error('CommandSender.replyMethodFor needs a requestId'); | ||
} | ||
return function(command, payload){ | ||
payload == null && (payload = {}); | ||
return this$.send(command, payload, { | ||
responseTo: requestId | ||
}); | ||
}; | ||
}; | ||
prototype.send = function(command, payload, options){ | ||
var requestData; | ||
payload == null && (payload = {}); | ||
options == null && (options = {}); | ||
switch (false) { | ||
case !!command: | ||
throw new Error('ExoRelay#send cannot send empty commands'); | ||
case typeof command === 'string': | ||
throw new Error('ExoRelay#send can only send string commands'); | ||
case typeof payload !== 'function': | ||
throw new Error('ExoRelay#send cannot send functions as payload'); | ||
} | ||
this._log(command, options); | ||
requestData = { | ||
method: 'POST', | ||
url: "http://localhost:" + this.exocommPort + "/send/" + obj.command, | ||
url: "http://localhost:" + this.exocommPort + "/send/" + command, | ||
json: true, | ||
body: { | ||
'request-id': uuid.v1() | ||
requestId: uuid.v1() | ||
} | ||
}; | ||
if (obj.payload) { | ||
options.body.payload = obj.payload; | ||
if (!isEmpty(payload)) { | ||
requestData.body.payload = payload; | ||
} | ||
if (obj.replyingTo) { | ||
options.body['replying-to'] = obj.replyingTo; | ||
if (options.responseTo) { | ||
requestData.body.responseTo = options.responseTo; | ||
} | ||
request(options, function(err, response, body){ | ||
request(requestData, function(err, response, body){ | ||
if (err || (response != null ? response.statusCode : void 8) !== 200) { | ||
debug("Error sending command '" + obj.command + "'"); | ||
debug("Error sending command '" + command + "'"); | ||
debug("* err: " + err); | ||
@@ -40,4 +65,12 @@ return debug("* response: " + (response != null ? response.statusCode : void 8)); | ||
}); | ||
return options.body['request-id']; | ||
return this.lastSentRequestId = requestData.body.requestId; | ||
}; | ||
prototype._log = function(command, options){ | ||
switch (false) { | ||
case !options.responseTo: | ||
return debug("sending command '" + command + "' in response to '" + options.responseTo + "'"); | ||
default: | ||
return debug("sending command '" + command + "'"); | ||
} | ||
}; | ||
return CommandSender; | ||
@@ -44,0 +77,0 @@ }()); |
@@ -33,5 +33,9 @@ // Generated by LiveScript 1.4.0 | ||
} | ||
prototype.send = function(command, replyHandler){ | ||
prototype.send = function(command, payload, replyHandler){ | ||
var requestId; | ||
requestId = this.commandSender.send(command); | ||
switch (false) { | ||
case !(replyHandler && typeof replyHandler !== 'function'): | ||
throw new Error('The reply handler given to ExoRelay#send must be a function'); | ||
} | ||
requestId = this.commandSender.send(command, payload); | ||
if (replyHandler) { | ||
@@ -43,3 +47,5 @@ this.commandHandler.registerReplyHandler(requestId, replyHandler); | ||
prototype._onIncomingCommand = function(requestData){ | ||
return this.commandHandler.handleRequest(requestData); | ||
return this.commandHandler.handleRequest(requestData, { | ||
reply: this.commandSender.replyMethodFor(requestData.requestId) | ||
}); | ||
}; | ||
@@ -46,0 +52,0 @@ return ExoRelay; |
@@ -15,7 +15,7 @@ // Generated by LiveScript 1.4.0 | ||
}; | ||
prototype.handle = function(requestId, requestData){ | ||
prototype.handle = function(requestId, requestData, methods){ | ||
var handler; | ||
if (handler = this.getHandler(requestId)) { | ||
this.debug("handling command '" + requestId + "'"); | ||
handler(requestData); | ||
handler(requestData, methods); | ||
} | ||
@@ -29,2 +29,10 @@ return !!handler; | ||
switch (false) { | ||
case !!requestId: | ||
throw new Error("No request id provided"); | ||
case typeof requestId === 'string': | ||
throw new Error("Request ids must be strings"); | ||
case !!handler: | ||
throw new Error("No command handler provided"); | ||
case typeof handler === 'function': | ||
throw new Error("Command handler must be a function"); | ||
case !this.hasHandler(requestId): | ||
@@ -31,0 +39,0 @@ throw new Error("There is already a handler for command '" + requestId + "'"); |
@@ -19,10 +19,14 @@ // Generated by LiveScript 1.4.0 | ||
prototype.close = function(){ | ||
debug("no longer listening at port " + this.port); | ||
return this.server.close(); | ||
if (this.server) { | ||
debug("no longer listening at port " + this.port); | ||
return this.server.close(); | ||
} | ||
}; | ||
prototype.listen = function(port, done){ | ||
this.port = port; | ||
this.port = +port; | ||
switch (false) { | ||
case typeof port !== 'function': | ||
return this.listen(4000, port); | ||
case !isNaN(this.port): | ||
throw new Error('Non-numerical port provided to ExoRelay#listen'); | ||
} | ||
@@ -47,10 +51,6 @@ return this.server = this.app.listen(port, function(){ | ||
prototype._commandController = function(req, res){ | ||
var ref$, command, replyingTo, payload; | ||
ref$ = this._parseRequest(req), command = ref$[0], replyingTo = ref$[1], payload = ref$[2]; | ||
this._log(command, replyingTo); | ||
if (this.handleCommand({ | ||
command: command, | ||
replyingTo: replyingTo, | ||
payload: payload | ||
})) { | ||
var requestData; | ||
requestData = this._parseRequest(req); | ||
this._log(requestData.command, requestData.responseTo); | ||
if (this.handleCommand(requestData)) { | ||
return res.status(200).end(); | ||
@@ -61,6 +61,6 @@ } else { | ||
}; | ||
prototype._log = function(command, replyingTo){ | ||
prototype._log = function(command, responseTo){ | ||
switch (false) { | ||
case !replyingTo: | ||
return debug("received command '" + command + "' in reply to '" + replyingTo + "'"); | ||
case !responseTo: | ||
return debug("received command '" + command + "' in response to '" + responseTo + "'"); | ||
default: | ||
@@ -74,7 +74,13 @@ return debug("received command '" + command + "'"); | ||
prototype._parseRequest = function(req){ | ||
var command, payload, replyingTo; | ||
var command, payload, responseTo, requestId; | ||
command = req.params.command; | ||
payload = req.body.payload; | ||
replyingTo = req.body['replying-to']; | ||
return [command, replyingTo, payload]; | ||
responseTo = req.body.responseTo; | ||
requestId = req.body.requestId; | ||
return { | ||
command: command, | ||
responseTo: responseTo, | ||
payload: payload, | ||
requestId: requestId | ||
}; | ||
}; | ||
@@ -81,0 +87,0 @@ return HttpListener; |
{ | ||
"name": "exorelay", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Communication relay between JavaScript code bases and the Exosphere environment", | ||
@@ -29,3 +29,3 @@ "main": "lib/exorelay.js", | ||
"node-uuid": "^1.4.7", | ||
"rails-delegate": "^0.1.0", | ||
"rails-delegate": "^0.2.0", | ||
"request": "^2.67.0" | ||
@@ -40,5 +40,8 @@ }, | ||
"livescript": "^1.4.0", | ||
"lodash.isempty": "^4.0.0", | ||
"lodash.isequal": "^4.0.0", | ||
"mocha": "^2.3.4", | ||
"nitroglycerin": "^1.0.3", | ||
"portfinder": "^0.4.0", | ||
"record-http": "^0.2.1", | ||
"record-http": "^0.4.0", | ||
"sinon": "^1.17.2", | ||
@@ -45,0 +48,0 @@ "wait": "^0.1.0" |
@@ -16,61 +16,54 @@ # Exosphere Communication Relay for JavaScript | ||
```javascript | ||
ExoRelay = require("exorelay"); | ||
Each code base should have only one ExoRelay instance. | ||
exoRelay = new ExoRelay(); | ||
exoRelay.listen(); | ||
```coffeescript | ||
ExoRelay = require 'exorelay' | ||
exoRelay = new ExoRelay() | ||
exoRelay.listen() | ||
``` | ||
More details and how to customize the port is described in the [spec](features/listen.feature) | ||
More details and how to customize the port is described in the [spec](features/listen.feature). | ||
## Handle incoming commands | ||
## Send outgoing commands | ||
Register a handler for incoming commands: | ||
Send a command to Exosphere: | ||
```javascript | ||
exoRelay.registerHandler("hello", function(payload) { | ||
console.log("Hello " + payload.name); | ||
}); | ||
```coffeescript | ||
exoRelay.send 'hello', name: 'world' | ||
``` | ||
Test this setup: | ||
Sending a command is fire-and-forget, i.e. you don't have to wait for the | ||
sending process to finish before you can do the next thing. | ||
More details on how to send various data are [here](features/sending.feature). | ||
```bash | ||
$ curl -d '{"name": "Joe"}' http://localhost:4000/run/hello_name | ||
You can handle the incoming replies to your outgoing commands: | ||
```coffeescript | ||
exo-relay.send 'users.create', name: 'Will Riker', (createdUser) -> | ||
print "created user #{createdUser.id}" | ||
``` | ||
More details in the [spec](features/receiving-commands.feature) | ||
More examples for handling incoming replies are [here](features/incoming-replies.feature). | ||
## Send outgoing commands | ||
## Handle incoming commands | ||
Send a command to Exosphere: | ||
Register a handler for incoming commands: | ||
```javascript | ||
exoRelay.send({ command: "hello", payload: { name: "world" }}, done); | ||
```coffeescript | ||
exoRelay.registerHandler 'hello', (name) -> | ||
console.log "Hello #{name}" | ||
``` | ||
More details in the [spec](features/sending-commands.feature) | ||
More details on how to define command listeners are [here](features/receiving-commands.feature). | ||
If you are implementing services, you want to send outgoing replies to incoming commands: | ||
## Replies to commands | ||
Commands can be replies to other commands. | ||
Each command has a unique _command-id_. | ||
Other commands can reference the id of another command | ||
to indicate that they are a reply to that command. | ||
As an example, let's send out a "users/create" command, | ||
and handle the reply to it (which the "users" service will send out): | ||
```javascript | ||
exoRelay.send({ command: "users/create", payload: { name: "Jean-Luc" } }, function(createdUser) { | ||
console.log("user " + createdUser.id + " created"); | ||
}); | ||
```coffeescript | ||
exoRelay.registerHandler 'users.create', (userData, {reply}) -> | ||
# on this line we would create a user database record with the attributes given in userData | ||
reply 'users.created', id: 456, name: userData.name | ||
``` | ||
The "users" service would be implemented using the | ||
[ExoService-JS tool](https://github.com/Originate/exoservice-js). | ||
More details in the [spec](features/sending-commands.feature) | ||
More details and a working example of how to send replies is [here](features/outgoing-replies.feature). |
17401
11
357
14
69
+ Addedlodash.flatten@4.4.0(transitive)
+ Addedrails-delegate@0.2.0(transitive)
- Removedlodash._baseflatten@3.1.4(transitive)
- Removedlodash._isiterateecall@3.0.9(transitive)
- Removedlodash.flatten@3.0.2(transitive)
- Removedlodash.isarguments@3.1.0(transitive)
- Removedlodash.isarray@3.0.4(transitive)
- Removedrails-delegate@0.1.0(transitive)
Updatedrails-delegate@^0.2.0