Skip to content

Commit

Permalink
feature(script): improve cancel()
Browse files Browse the repository at this point in the history
Allows passing an error object to `cancel(err)`, or an exception object returned by the deployd internal-client (eg. {message: "", status: 400}).

This allows easy chaining such as (in an event script):

```javascript
// call some other collection via internal-client
// both cases are handled by the new cancel, whether the code throws an Error object, or if .get returns an exception of the form {message, status}
dpd.somecol.get({...}).then(function() { error may get thrown here }.catch(cancel);
```
  • Loading branch information
andreialecu committed Jul 14, 2015
1 parent 84a1d03 commit 5bad106
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 3 deletions.
6 changes: 5 additions & 1 deletion lib/internal-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ exports.build = function(server, session, stack, ctx) {
callback(data, null);
}
} else {
callback(null, data);
try {
callback(null, JSON.parse(data));
} catch (ex) {
callback(null, data);
}
}
},
internal: true,
Expand Down
17 changes: 15 additions & 2 deletions lib/script.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
var _ = require('underscore')._
, EventEmitter = require('events').EventEmitter
, fs = require('fs')
, bluebird = require('bluebird');
, bluebird = require('bluebird')
, util = require('util');

/**
* A `Script` executes JavaScript src in a sandboxed context and exposes it a set of domain functions.
Expand Down Expand Up @@ -46,12 +47,22 @@ Script.prototype.run = function (ctx, domain, fn) {
, session = ctx.session
, waitingForCallback = false
, callbackCount = 0
, isDone = false
, events;

var scriptContext = {
'this': {},
cancel: function(msg, status) {
var err = {message: msg, statusCode: status};
var err;
if (util.isError(msg)) {
err = msg;
} else if (!status && msg && msg.message && (msg.status || msg.statusCode)) {
// allow chaining this from another response
err = {message: msg.message, statusCode: msg.status || msg.statusCode};
} else {
err = {message: msg, statusCode: status};
}
done(err);
throw err;
},
cancelIf: function(condition, msg, status) {
Expand Down Expand Up @@ -88,6 +99,8 @@ Script.prototype.run = function (ctx, domain, fn) {
events = new EventEmitter();

function done(err) {
if (isDone) return;
isDone = true;
events.removeAllListeners('finishCallback');
if (fn) fn(err);
}
Expand Down
19 changes: 19 additions & 0 deletions test/script.unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@ describe('script', function(){
});
});

it('should keep error intact when calling cancel(err)', function(done) {
var s = new Script('cancel(new Error("test"))');
s.run({}, function (e) {
expect(e).to.exist;
expect(e.message).to.equal('test');
done();
});
});

it('should keep object intact when calling cancel({message: , status: })', function(done) {
var s = new Script('cancel({message: "test", status: 404})');
s.run({}, function (e) {
expect(e).to.exist;
expect(e.message).to.equal('test');
expect(e.statusCode).to.equal('404'); // status is turned into statusCode
done();
});
});

it('should have access to the current user if one exists', function(done) {
var s = new Script('if(!me) throw "no user"');
var session = {
Expand Down

0 comments on commit 5bad106

Please sign in to comment.