Updated README, consolidated standard and AMD build processes

This commit is contained in:
Jim Cowart 2012-03-20 02:04:35 -04:00
parent e542269058
commit b48bdfc276
32 changed files with 810 additions and 1056 deletions

View file

@ -22,13 +22,16 @@ JavaScript:
```javascript
// The world's simplest subscription
var channel = postal.channel("Name.Changed");
// doesn't specify a channel name, so it defaults to "/" (DEFAULT_CHANNEL)
var channel = postal.channel( { topic: "Name.Changed" } );
// subscribe
var subscription = channel.subscribe(function(data) { $("#example1").html("Name: " + data.name); });
var subscription = channel.subscribe( function( data, envelope ) {
$( "#example1" ).html( "Name: " + data.name );
});
// And someone publishes a first name change:
channel.publish({ name: "Dr. Who" });
channel.publish( { name: "Dr. Who" } );
subscription.unsubscribe();
```
@ -37,14 +40,14 @@ subscription.unsubscribe();
The `#` symbol represents "one word" in a topic (i.e - the text between two periods of a topic). By subscribing to `"#.Changed"`, the binding will match `Name.Changed` & `Location.Changed` but *not* for `Changed.Companion`
```javascript
var hashChannel = postal.channel("#.Changed"),
chgSubscription = hashChannel.subscribe(function(data) {
$('<li>' + data.type + " Changed: " + data.value + '</li>').appendTo("#example2");
var hashChannel = postal.channel( { topic: "#.Changed" } ),
chgSubscription = hashChannel.subscribe( function( data ) {
$( '<li>' + data.type + " Changed: " + data.value + '</li>' ).appendTo( "#example2" );
});
postal.channel("Name.Changed")
.publish({ type: "Name", value:"John Smith" });
postal.channel("Location.Changed")
.publish({ type: "Location", value: "Early 20th Century England" });
postal.channel( { topic: "Name.Changed" } )
.publish( { type: "Name", value:"John Smith" } );
postal.channel( "Location.Changed" )
.publish( { type: "Location", value: "Early 20th Century England" } );
chgSubscription.unsubscribe();
```
@ -53,40 +56,38 @@ chgSubscription.unsubscribe();
The `*` symbol represents any number of characters/words in a topic string. By subscribing to ``"DrWho.*.Changed"``, the binding will match `DrWho.NinthDoctor.Companion.Changed` & `DrWho.Location.Changed` but *not* `Changed`
```javascript
var starChannel = postal.channel("DrWho.*.Changed"),
starSubscription = starChannel.subscribe(function(data) {
$('<li>' + data.type + " Changed: " + data.value + '</li>').appendTo("#example3");
var starChannel = postal.channel( { channel: "Doctor.Who", topic: "DrWho.*.Changed" } ),
starSubscription = starChannel.subscribe( function( data ) {
$( '<li>' + data.type + " Changed: " + data.value + '</li>' ).appendTo( "#example3" );
});
postal.channel("DrWho.NinthDoctor.Companion.Changed")
.publish({ type: "Name", value:"Rose" });
postal.channel("DrWho.TenthDoctor.Companion.Changed")
.publish({ type: "Name", value:"Martha" });
postal.channel("DrWho.Eleventh.Companion.Changed")
.publish({ type: "Name", value:"Amy" });
postal.channel("DrWho.Location.Changed")
.publish({ type: "Location", value: "The Library" });
postal.channel("TheMaster.DrumBeat.Changed")
.publish({ type: "DrumBeat", value: "This won't trigger any subscriptions" });
postal.channel("Changed")
.publish({ type: "Useless", value: "This won't trigger any subscriptions either" });
// demonstrating how we're re-using the channel delcared above to publish, but overriding the topic in the second argument
starChannel.publish( { type: "Name", value:"Rose" }, { topic: "DrWho.NinthDoctor.Companion.Changed" } );
starChannel.publish( { type: "Name", value:"Martha" }, { topic: "DrWho.TenthDoctor.Companion.Changed" } );
starChannel.publish( { type: "Name", value:"Amy" }, { topic: "DrWho.Eleventh.Companion.Changed" } );
starChannel.publish( { type: "Location", value: "The Library" }, { topic: "DrWho.Location.Changed" } );
starChannel.publish( { type: "DrumBeat", value: "This won't trigger any subscriptions" }, { topic: "TheMaster.DrumBeat.Changed" } );
starChannel.publish( { type: "Useless", value: "This won't trigger any subscriptions either" }, { topic: "Changed" } );
starSubscription.unsubscribe();
```
### Applying ignoreDuplicates to a subscription
```javascript
var dupChannel = postal.channel("WeepingAngel.*"),
dupSubscription = dupChannel.subscribe(function(data) {
$('<li>' + data.value + '</li>').appendTo("#example4");
var dupChannel = postal.channel( { topic: "WeepingAngel.*" } ),
dupSubscription = dupChannel.subscribe( function( data ) {
$( '<li>' + data.value + '</li>' ).appendTo( "#example4" );
}).ignoreDuplicates();
postal.channel("WeepingAngel.DontBlink")
.publish({ value:"Don't Blink" });
postal.channel("WeepingAngel.DontBlink")
.publish({ value:"Don't Blink" });
postal.channel("WeepingAngel.DontEvenBlink")
.publish({ value:"Don't Even Blink" });
postal.channel("WeepingAngel.DontBlink")
.publish({ value:"Don't Close Your Eyes" });
// demonstrating multiple channels per topic being used
// You can do it this way if you like, but the example above has nicer syntax (and less overhead)
postal.channel( { topic: "WeepingAngel.DontBlink" } )
.publish( { value:"Don't Blink" } );
postal.channel( { topic: "WeepingAngel.DontBlink" } )
.publish( { value:"Don't Blink" } );
postal.channel( { topic: "WeepingAngel.DontEvenBlink" } )
.publish( { value:"Don't Even Blink" } );
postal.channel( { topic: "WeepingAngel.DontBlink" } )
.publish( { value:"Don't Close Your Eyes" } );
dupSubscription.unsubscribe();
```
@ -104,7 +105,5 @@ Please - by all means! While I hope the API is relatively stable, I'm open to p
## Roadmap for the Future
Here's where Postal is headed:
* The original proof-of-concept version of postal supported the ability to capture messages and replay them. This functionality will be added soon.
* The ability to 'join' two (or more) subscriptions, so that the original subscription will only fire once the second "joined" subscription has also fired. Think of it as a message-based version of a compound promise.
* I haven't yet thoroughly tested Postal on Node.js - that is high on my list as well.
* What else would you like to see?

View file

@ -2,12 +2,14 @@
anvil -b build-browser-standard.json
anvil -b build-browser-standard-diags.json
anvil -b build-browser-amd.json
anvil -b build-browser-amd-diags.json
anvil -b build-node.json
anvil -b build-node-diags.json
cp ./lib/browser/amd/postal.js ./example/amd/js/libs/postal/
cp ./lib/browser/amd/postal.diagnostics.js ./example/amd/js/libs/postal/
cp ./lib/browser/standard/postal.js ./example/amd/js/libs/postal/
cp ./lib/browser/standard/postal.diagnostics.js ./example/amd/js/libs/postal/
cp ./lib/browser/standard/postal.js ./example/standard/js/
cp ./lib/browser/standard/postal.diagnostics.js ./example/standard/js/
cp ./lib/browser/standard/postal.diagnostics.js ./example/standard/js/
mv ./lib/browser/standard/postal.node.js ./lib/node/postal.js
rm ./lib/browser/standard/postal.node*
mv ./lib/browser/standard/postal.diagnostics.node.js ./lib/node/postal.diagnostics.js
rm ./lib/browser/standard/postal.diagnostics.node*

View file

@ -1,12 +0,0 @@
{
"source": "src/diags",
"output": "lib/browser/amd",
"lint": {},
"uglify": {},
"gzip": {},
"extensions": { "uglify": "min", "gzip": "gz" },
"wrap": {
"prefix": "define(['postal', 'underscore'], function(postal, _) {",
"suffix": "});"
}
}

View file

@ -1,12 +0,0 @@
{
"source": "src/main",
"output": "lib/browser/amd",
"lint": {},
"uglify": {},
"gzip": {},
"extensions": { "uglify": "min", "gzip": "gz" },
"wrap": {
"prefix": "define(['underscore'], function(_) {",
"suffix": "return postal; });"
}
}

View file

@ -4,9 +4,5 @@
"lint": {},
"uglify": {},
"gzip": {},
"extensions": { "uglify": "min", "gzip": "gz" },
"wrap": {
"prefix": "(function(global, undefined) {",
"suffix": "global.postal = postal; })(window);"
}
"extensions": { "uglify": "min", "gzip": "gz" }
}

View file

@ -1,9 +1,5 @@
{
"source": "src/diags",
"output": "lib/node",
"lint": {},
"wrap": {
"prefix": "module.exports = function(postal) {",
"suffix": "};"
}
"lint": {}
}

View file

@ -1,9 +1,5 @@
{
"source": "src/main",
"output": "lib/node",
"lint": {},
"wrap": {
"prefix": "var _ = require('underscore');",
"suffix": "module.exports = postal;"
}
"lint": {}
}

View file

@ -1,20 +1,33 @@
define(['postal', 'underscore'], function(postal, _) {
postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
});
(function(root, doc, factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["postal", "underscore"], function(postal, _) {
return factory(postal, _, root, doc);
});
} else {
// Browser globals
factory(root.postal, root._, root, doc);
}
}(this, document, function(postal, _, global, document, undefined) {
// this returns a callback that, if invoked, removes the wireTap
return postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
}));

View file

@ -1,4 +1,3 @@
define(['underscore'], function(_) {
/*
postal.js
Author: Jim Cowart
@ -6,6 +5,18 @@ define(['underscore'], function(_) {
Version 0.4.0
*/
(function(root, doc, factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["underscore"], function(_) {
return factory(_, root, doc);
});
} else {
// Browser globals
factory(root._, root, doc);
}
}(this, document, function(_, global, document, undefined) {
var DEFAULT_CHANNEL = "/",
DEFAULT_PRIORITY = 50,
DEFAULT_DISPOSEAFTER = 0,
@ -34,8 +45,14 @@ var ChannelDefinition = function(channelName, defaultTopic) {
};
ChannelDefinition.prototype = {
subscribe: function(callback) {
return new SubscriptionDefinition(this.channel, this.topic, callback);
subscribe: function() {
var len = arguments.length;
if(len === 1) {
return new SubscriptionDefinition(this.channel, this.topic, arguments[0]);
}
else if (len === 2) {
return new SubscriptionDefinition(this.channel, arguments[0], arguments[1]);
}
},
publish: function(data, envelope) {
@ -43,142 +60,140 @@ ChannelDefinition.prototype = {
env.channel = this.channel;
env.timeStamp = new Date();
env.topic = env.topic || this.topic;
postal.configuration.bus.publish(env, data);
postal.configuration.bus.publish(data, env);
}
};
var SubscriptionDefinition = function(channel, topic, callback) {
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
postal.publish({
event: "subscription.created",
channel: channel,
topic: topic
},{
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
});
postal.configuration.bus.subscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
},
{
event: "subscription.created",
channel: channel,
topic: topic
});
};
SubscriptionDefinition.prototype = {
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
},
{
event: "subscription.removed",
channel: this.channel,
topic: this.topic
});
},
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
event: "subscription.removed",
channel: this.channel,
topic: this.topic
},{
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
});
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withContext: function(context) {
this.context = context;
return this;
},
withContext: function(context) {
this.context = context;
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
};
var bindingsResolver = {
@ -209,9 +224,9 @@ var localBus = {
wireTaps: new Array(0),
publish: function(envelope, data) {
publish: function(data, envelope) {
_.each(this.wireTaps,function(tap) {
tap(envelope, data);
tap(data, envelope);
});
_.each(this.subscriptions[envelope.channel], function(topic) {
@ -279,14 +294,14 @@ var localBus = {
};
var publishPicker = {
"2" : function(envelope, payload) {
"2" : function(data, envelope) {
if(!envelope.channel) {
envelope.channel = DEFAULT_CHANNEL;
}
postal.configuration.bus.publish(envelope, payload);
postal.configuration.bus.publish(data, envelope);
},
"3" : function(channel, topic, payload) {
postal.configuration.bus.publish({ channel: channel, topic: topic }, payload);
postal.configuration.bus.publish(payload, { channel: channel, topic: topic });
}
};
@ -343,7 +358,7 @@ var postal = {
var newEnv = env;
newEnv.topic = _.isFunction(destination.topic) ? destination.topic(env.topic) : destination.topic || env.topic;
newEnv.channel = destChannel;
postal.publish(newEnv, msg);
postal.publish(msg, newEnv);
}
})
);
@ -352,5 +367,8 @@ var postal = {
return result;
}
};
return postal; });
global.postal = postal;
return postal;
}));

View file

@ -1,18 +1,33 @@
postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
(function(root, doc, factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["postal", "underscore"], function(postal, _) {
return factory(postal, _, root, doc);
});
} else {
// Browser globals
factory(root.postal, root._, root, doc);
}
}(this, document, function(postal, _, global, document, undefined) {
// this returns a callback that, if invoked, removes the wireTap
return postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
}));

View file

@ -1,4 +1,3 @@
(function(global, undefined) {
/*
postal.js
Author: Jim Cowart
@ -6,6 +5,18 @@
Version 0.4.0
*/
(function(root, doc, factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["underscore"], function(_) {
return factory(_, root, doc);
});
} else {
// Browser globals
factory(root._, root, doc);
}
}(this, document, function(_, global, document, undefined) {
var DEFAULT_CHANNEL = "/",
DEFAULT_PRIORITY = 50,
DEFAULT_DISPOSEAFTER = 0,
@ -34,8 +45,14 @@ var ChannelDefinition = function(channelName, defaultTopic) {
};
ChannelDefinition.prototype = {
subscribe: function(callback) {
return new SubscriptionDefinition(this.channel, this.topic, callback);
subscribe: function() {
var len = arguments.length;
if(len === 1) {
return new SubscriptionDefinition(this.channel, this.topic, arguments[0]);
}
else if (len === 2) {
return new SubscriptionDefinition(this.channel, arguments[0], arguments[1]);
}
},
publish: function(data, envelope) {
@ -43,142 +60,140 @@ ChannelDefinition.prototype = {
env.channel = this.channel;
env.timeStamp = new Date();
env.topic = env.topic || this.topic;
postal.configuration.bus.publish(env, data);
postal.configuration.bus.publish(data, env);
}
};
var SubscriptionDefinition = function(channel, topic, callback) {
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
postal.publish({
event: "subscription.created",
channel: channel,
topic: topic
},{
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
});
postal.configuration.bus.subscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
},
{
event: "subscription.created",
channel: channel,
topic: topic
});
};
SubscriptionDefinition.prototype = {
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
},
{
event: "subscription.removed",
channel: this.channel,
topic: this.topic
});
},
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
event: "subscription.removed",
channel: this.channel,
topic: this.topic
},{
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
});
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withContext: function(context) {
this.context = context;
return this;
},
withContext: function(context) {
this.context = context;
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
};
var bindingsResolver = {
@ -209,9 +224,9 @@ var localBus = {
wireTaps: new Array(0),
publish: function(envelope, data) {
publish: function(data, envelope) {
_.each(this.wireTaps,function(tap) {
tap(envelope, data);
tap(data, envelope);
});
_.each(this.subscriptions[envelope.channel], function(topic) {
@ -279,14 +294,14 @@ var localBus = {
};
var publishPicker = {
"2" : function(envelope, payload) {
"2" : function(data, envelope) {
if(!envelope.channel) {
envelope.channel = DEFAULT_CHANNEL;
}
postal.configuration.bus.publish(envelope, payload);
postal.configuration.bus.publish(data, envelope);
},
"3" : function(channel, topic, payload) {
postal.configuration.bus.publish({ channel: channel, topic: topic }, payload);
postal.configuration.bus.publish(payload, { channel: channel, topic: topic });
}
};
@ -343,7 +358,7 @@ var postal = {
var newEnv = env;
newEnv.topic = _.isFunction(destination.topic) ? destination.topic(env.topic) : destination.topic || env.topic;
newEnv.channel = destChannel;
postal.publish(newEnv, msg);
postal.publish(msg, newEnv);
}
})
);
@ -352,5 +367,8 @@ var postal = {
return result;
}
};
global.postal = postal; })(window);
global.postal = postal;
return postal;
}));

View file

@ -1,20 +0,0 @@
define(['postal', 'underscore'], function(postal, _) {
postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
});

View file

@ -1 +0,0 @@
define(["postal","underscore"],function(a,b){a.addWireTap(function(a,c){var d=b.extend(c,{data:a});if(!JSON)throw"This browser or environment does not provide JSON support";try{console.log(JSON.stringify(d))}catch(e){try{d.data="ERROR: "+e.message,console.log(JSON.stringify(d))}catch(f){console.log("Unable to parse data to JSON: "+e)}}})})

View file

@ -1,356 +0,0 @@
define(['underscore'], function(_) {
/*
postal.js
Author: Jim Cowart
License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
Version 0.4.0
*/
var DEFAULT_CHANNEL = "/",
DEFAULT_PRIORITY = 50,
DEFAULT_DISPOSEAFTER = 0,
SYSTEM_CHANNEL = "postal",
NO_OP = function() { };
var DistinctPredicate = function() {
var previous;
return function(data) {
var eq = false;
if(_.isString(data)) {
eq = data === previous;
previous = data;
}
else {
eq = _.isEqual(data, previous);
previous = _.clone(data);
}
return !eq;
};
};
var ChannelDefinition = function(channelName, defaultTopic) {
this.channel = channelName;
this.topic = defaultTopic || "";
};
ChannelDefinition.prototype = {
subscribe: function(callback) {
return new SubscriptionDefinition(this.channel, this.topic, callback);
},
publish: function(data, envelope) {
var env = envelope || {};
env.channel = this.channel;
env.timeStamp = new Date();
env.topic = env.topic || this.topic;
postal.configuration.bus.publish(env, data);
}
};
var SubscriptionDefinition = function(channel, topic, callback) {
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
postal.configuration.bus.subscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
},
{
event: "subscription.created",
channel: channel,
topic: topic
});
};
SubscriptionDefinition.prototype = {
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
},
{
event: "subscription.removed",
channel: this.channel,
topic: this.topic
});
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withContext: function(context) {
this.context = context;
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
};
var bindingsResolver = {
cache: { },
compare: function(binding, topic) {
if(this.cache[topic] && this.cache[topic][binding]) {
return true;
}
// binding.replace(/\./g,"\\.") // escape actual periods
// .replace(/\*/g, ".*") // asterisks match any value
// .replace(/#/g, "[A-Z,a-z,0-9]*"); // hash matches any alpha-numeric 'word'
var rgx = new RegExp("^" + binding.replace(/\./g,"\\.").replace(/\*/g, ".*").replace(/#/g, "[A-Z,a-z,0-9]*") + "$"),
result = rgx.test(topic);
if(result) {
if(!this.cache[topic]) {
this.cache[topic] = {};
}
this.cache[topic][binding] = true;
}
return result;
}
};
var localBus = {
subscriptions: {},
wireTaps: new Array(0),
publish: function(envelope, data) {
_.each(this.wireTaps,function(tap) {
tap(envelope, data);
});
_.each(this.subscriptions[envelope.channel], function(topic) {
_.each(topic, function(binding){
if(postal.configuration.resolver.compare(binding.topic, envelope.topic)) {
if(_.all(binding.constraints, function(constraint) { return constraint(data); })) {
if(typeof binding.callback === 'function') {
binding.callback.apply(binding.context, [data, envelope]);
binding.onHandled();
}
}
}
});
});
},
subscribe: function(subDef) {
var idx, found, fn, channel = this.subscriptions[subDef.channel], subs;
if(!channel) {
channel = this.subscriptions[subDef.channel] = {};
}
subs = this.subscriptions[subDef.channel][subDef.topic];
if(!subs) {
subs = this.subscriptions[subDef.channel][subDef.topic] = new Array(0);
}
idx = subs.length - 1;
for(; idx >= 0; idx--) {
if(subs[idx].priority <= subDef.priority) {
subs.splice(idx + 1, 0, subDef);
found = true;
break;
}
}
if(!found) {
subs.unshift(subDef);
}
return subDef;
},
unsubscribe: function(config) {
if(this.subscriptions[config.channel][config.topic]) {
var len = this.subscriptions[config.channel][config.topic].length,
idx = 0;
for ( ; idx < len; idx++ ) {
if (this.subscriptions[config.channel][config.topic][idx] === config) {
this.subscriptions[config.channel][config.topic].splice( idx, 1 );
break;
}
}
}
},
addWireTap: function(callback) {
var self = this;
self.wireTaps.push(callback);
return function() {
var idx = self.wireTaps.indexOf(callback);
if(idx !== -1) {
self.wireTaps.splice(idx,1);
}
};
}
};
var publishPicker = {
"2" : function(envelope, payload) {
if(!envelope.channel) {
envelope.channel = DEFAULT_CHANNEL;
}
postal.configuration.bus.publish(envelope, payload);
},
"3" : function(channel, topic, payload) {
postal.configuration.bus.publish({ channel: channel, topic: topic }, payload);
}
};
// save some setup time, albeit tiny
localBus.subscriptions[SYSTEM_CHANNEL] = {};
var postal = {
configuration: {
bus: localBus,
resolver: bindingsResolver
},
channel: function(options) {
var channel = options.channel || DEFAULT_CHANNEL,
tpc = options.topic;
return new ChannelDefinition(channel, tpc);
},
subscribe: function(options) {
var callback = options.callback,
topic = options.topic,
channel = options.channel || DEFAULT_CHANNEL;
return new SubscriptionDefinition(channel, topic, callback);
},
publish: function() {
var len = arguments.length;
if(publishPicker[len]) {
publishPicker[len].apply(this, arguments);
}
},
addWireTap: function(callback) {
return this.configuration.bus.addWireTap(callback);
},
linkChannels: function(sources, destinations) {
var result = [];
if(!_.isArray(sources)) {
sources = [sources];
}
if(!_.isArray(destinations)) {
destinations = [destinations];
}
_.each(sources, function(source){
var sourceTopic = source.topic || "*";
_.each(destinations, function(destination) {
var destChannel = destination.channel || DEFAULT_CHANNEL;
result.push(
postal.subscribe({
channel: source.channel || DEFAULT_CHANNEL,
topic: source.topic || "*",
callback : function(msg, env) {
var newEnv = env;
newEnv.topic = _.isFunction(destination.topic) ? destination.topic(env.topic) : destination.topic || env.topic;
newEnv.channel = destChannel;
postal.publish(newEnv, msg);
}
})
);
});
});
return result;
}
};
return postal; });

Binary file not shown.

View file

@ -1 +0,0 @@
define(["underscore"],function(a){var b="/",c=50,d=0,e="postal",f=function(){},g=function(){var b;return function(c){var d=!1;return a.isString(c)?(d=c===b,b=c):(d=a.isEqual(c,b),b=a.clone(c)),!d}},h=function(a,b){this.channel=a,this.topic=b||""};h.prototype={subscribe:function(a){return new i(this.channel,this.topic,a)},publish:function(a,b){var c=b||{};c.channel=this.channel,c.timeStamp=new Date,c.topic=c.topic||this.topic,m.configuration.bus.publish(c,a)}};var i=function(a,b,g){this.channel=a,this.topic=b,this.callback=g,this.priority=c,this.constraints=new Array(0),this.maxCalls=d,this.onHandled=f,this.context=null,m.configuration.bus.subscribe(this),m.publish({channel:e,topic:"subscription.created"},{event:"subscription.created",channel:a,topic:b})};i.prototype={unsubscribe:function(){m.configuration.bus.unsubscribe(this),m.publish({channel:e,topic:"subscription.removed"},{event:"subscription.removed",channel:this.channel,topic:this.topic})},defer:function(){var a=this.callback;return this.callback=function(b){setTimeout(a,0,b)},this},disposeAfter:function(b){if(a.isNaN(b)||b<=0)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var c=this.onHandled,d=a.after(b,a.bind(function(){this.unsubscribe(this)},this));return this.onHandled=function(){c.apply(this.context,arguments),d()},this},ignoreDuplicates:function(){return this.withConstraint(new g),this},whenHandledThenExecute:function(b){if(!a.isFunction(b))throw"Value provided to 'whenHandledThenExecute' must be a function";return this.onHandled=b,this},withConstraint:function(b){if(!a.isFunction(b))throw"Predicate constraint must be a function";return this.constraints.push(b),this},withConstraints:function(b){var c=this;return a.isArray(b)&&a.each(b,function(a){c.withConstraint(a)}),c},withContext:function(a){return this.context=a,this},withDebounce:function(b){if(a.isNaN(b))throw"Milliseconds must be a number";var c=this.callback;return this.callback=a.debounce(c,b),this},withDelay:function(b){if(a.isNaN(b))throw"Milliseconds must be a number";var c=this.callback;return this.callback=function(a){setTimeout(c,b,a)},this},withPriority:function(b){if(a.isNaN(b))throw"Priority must be a number";return this.priority=b,this},withThrottle:function(b){if(a.isNaN(b))throw"Milliseconds must be a number";var c=this.callback;return this.callback=a.throttle(c,b),this}};var j={cache:{},compare:function(a,b){if(this.cache[b]&&this.cache[b][a])return!0;var c=new RegExp("^"+a.replace(/\./g,"\\.").replace(/\*/g,".*").replace(/#/g,"[A-Z,a-z,0-9]*")+"$"),d=c.test(b);return d&&(this.cache[b]||(this.cache[b]={}),this.cache[b][a]=!0),d}},k={subscriptions:{},wireTaps:new Array(0),publish:function(b,c){a.each(this.wireTaps,function(a){a(b,c)}),a.each(this.subscriptions[b.channel],function(d){a.each(d,function(d){m.configuration.resolver.compare(d.topic,b.topic)&&a.all(d.constraints,function(a){return a(c)})&&typeof d.callback=="function"&&(d.callback.apply(d.context,[c,b]),d.onHandled())})})},subscribe:function(a){var b,c,d,e=this.subscriptions[a.channel],f;e||(e=this.subscriptions[a.channel]={}),f=this.subscriptions[a.channel][a.topic],f||(f=this.subscriptions[a.channel][a.topic]=new Array(0)),b=f.length-1;for(;b>=0;b--)if(f[b].priority<=a.priority){f.splice(b+1,0,a),c=!0;break}return c||f.unshift(a),a},unsubscribe:function(a){if(this.subscriptions[a.channel][a.topic]){var b=this.subscriptions[a.channel][a.topic].length,c=0;for(;c<b;c++)if(this.subscriptions[a.channel][a.topic][c]===a){this.subscriptions[a.channel][a.topic].splice(c,1);break}}},addWireTap:function(a){var b=this;return b.wireTaps.push(a),function(){var c=b.wireTaps.indexOf(a);c!==-1&&b.wireTaps.splice(c,1)}}},l={2:function(a,c){a.channel||(a.channel=b),m.configuration.bus.publish(a,c)},3:function(a,b,c){m.configuration.bus.publish({channel:a,topic:b},c)}};k.subscriptions[e]={};var m={configuration:{bus:k,resolver:j},channel:function(a){var c=a.channel||b,d=a.topic;return new h(c,d)},subscribe:function(a){var c=a.callback,d=a.topic,e=a.channel||b;return new i(e,d,c)},publish:function(){var a=arguments.length;l[a]&&l[a].apply(this,arguments)},addWireTap:function(a){return this.configuration.bus.addWireTap(a)},linkChannels:function(c,d){var e=[];return a.isArray(c)||(c=[c]),a.isArray(d)||(d=[d]),a.each(c,function(c){var f=c.topic||"*";a.each(d,function(d){var f=d.channel||b;e.push(m.subscribe({channel:c.channel||b,topic:c.topic||"*",callback:function(b,c){var e=c;e.topic=a.isFunction(d.topic)?d.topic(c.topic):d.topic||c.topic,e.channel=f,m.publish(e,b)}}))})}),e}};return m})

View file

@ -1,18 +1,33 @@
postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
(function(root, doc, factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["postal", "underscore"], function(postal, _) {
return factory(postal, _, root, doc);
});
} else {
// Browser globals
factory(root.postal, root._, root, doc);
}
}(this, document, function(postal, _, global, document, undefined) {
// this returns a callback that, if invoked, removes the wireTap
return postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
}));

View file

@ -1 +1 @@
postal.addWireTap(function(a,b){var c=_.extend(b,{data:a});if(!JSON)throw"This browser or environment does not provide JSON support";try{console.log(JSON.stringify(c))}catch(d){try{c.data="ERROR: "+d.message,console.log(JSON.stringify(c))}catch(e){console.log("Unable to parse data to JSON: "+d)}}})
(function(a,b,c){typeof define=="function"&&define.amd?define(["postal","underscore"],function(d,e){return c(d,e,a,b)}):c(a.postal,a._,a,b)})(this,document,function(a,b,c,d,e){return a.addWireTap(function(a,c){var d=b.extend(c,{data:a});if(!JSON)throw"This browser or environment does not provide JSON support";try{console.log(JSON.stringify(d))}catch(e){try{d.data="ERROR: "+e.message,console.log(JSON.stringify(d))}catch(f){console.log("Unable to parse data to JSON: "+e)}}})})

View file

@ -1,4 +1,3 @@
(function(global, undefined) {
/*
postal.js
Author: Jim Cowart
@ -6,6 +5,18 @@
Version 0.4.0
*/
(function(root, doc, factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["underscore"], function(_) {
return factory(_, root, doc);
});
} else {
// Browser globals
factory(root._, root, doc);
}
}(this, document, function(_, global, document, undefined) {
var DEFAULT_CHANNEL = "/",
DEFAULT_PRIORITY = 50,
DEFAULT_DISPOSEAFTER = 0,
@ -34,8 +45,14 @@ var ChannelDefinition = function(channelName, defaultTopic) {
};
ChannelDefinition.prototype = {
subscribe: function(callback) {
return new SubscriptionDefinition(this.channel, this.topic, callback);
subscribe: function() {
var len = arguments.length;
if(len === 1) {
return new SubscriptionDefinition(this.channel, this.topic, arguments[0]);
}
else if (len === 2) {
return new SubscriptionDefinition(this.channel, arguments[0], arguments[1]);
}
},
publish: function(data, envelope) {
@ -43,142 +60,140 @@ ChannelDefinition.prototype = {
env.channel = this.channel;
env.timeStamp = new Date();
env.topic = env.topic || this.topic;
postal.configuration.bus.publish(env, data);
postal.configuration.bus.publish(data, env);
}
};
var SubscriptionDefinition = function(channel, topic, callback) {
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
postal.publish({
event: "subscription.created",
channel: channel,
topic: topic
},{
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
});
postal.configuration.bus.subscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
},
{
event: "subscription.created",
channel: channel,
topic: topic
});
};
SubscriptionDefinition.prototype = {
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
},
{
event: "subscription.removed",
channel: this.channel,
topic: this.topic
});
},
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
event: "subscription.removed",
channel: this.channel,
topic: this.topic
},{
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
});
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withContext: function(context) {
this.context = context;
return this;
},
withContext: function(context) {
this.context = context;
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
};
var bindingsResolver = {
@ -209,9 +224,9 @@ var localBus = {
wireTaps: new Array(0),
publish: function(envelope, data) {
publish: function(data, envelope) {
_.each(this.wireTaps,function(tap) {
tap(envelope, data);
tap(data, envelope);
});
_.each(this.subscriptions[envelope.channel], function(topic) {
@ -279,14 +294,14 @@ var localBus = {
};
var publishPicker = {
"2" : function(envelope, payload) {
"2" : function(data, envelope) {
if(!envelope.channel) {
envelope.channel = DEFAULT_CHANNEL;
}
postal.configuration.bus.publish(envelope, payload);
postal.configuration.bus.publish(data, envelope);
},
"3" : function(channel, topic, payload) {
postal.configuration.bus.publish({ channel: channel, topic: topic }, payload);
postal.configuration.bus.publish(payload, { channel: channel, topic: topic });
}
};
@ -343,7 +358,7 @@ var postal = {
var newEnv = env;
newEnv.topic = _.isFunction(destination.topic) ? destination.topic(env.topic) : destination.topic || env.topic;
newEnv.channel = destChannel;
postal.publish(newEnv, msg);
postal.publish(msg, newEnv);
}
})
);
@ -352,5 +367,8 @@ var postal = {
return result;
}
};
global.postal = postal; })(window);
global.postal = postal;
return postal;
}));

View file

@ -1 +1 @@
(function(a,b){var c="/",d=50,e=0,f="postal",g=function(){},h=function(){var a;return function(b){var c=!1;return _.isString(b)?(c=b===a,a=b):(c=_.isEqual(b,a),a=_.clone(b)),!c}},i=function(a,b){this.channel=a,this.topic=b||""};i.prototype={subscribe:function(a){return new j(this.channel,this.topic,a)},publish:function(a,b){var c=b||{};c.channel=this.channel,c.timeStamp=new Date,c.topic=c.topic||this.topic,n.configuration.bus.publish(c,a)}};var j=function(a,b,c){this.channel=a,this.topic=b,this.callback=c,this.priority=d,this.constraints=new Array(0),this.maxCalls=e,this.onHandled=g,this.context=null,n.configuration.bus.subscribe(this),n.publish({channel:f,topic:"subscription.created"},{event:"subscription.created",channel:a,topic:b})};j.prototype={unsubscribe:function(){n.configuration.bus.unsubscribe(this),n.publish({channel:f,topic:"subscription.removed"},{event:"subscription.removed",channel:this.channel,topic:this.topic})},defer:function(){var a=this.callback;return this.callback=function(b){setTimeout(a,0,b)},this},disposeAfter:function(a){if(_.isNaN(a)||a<=0)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var b=this.onHandled,c=_.after(a,_.bind(function(){this.unsubscribe(this)},this));return this.onHandled=function(){b.apply(this.context,arguments),c()},this},ignoreDuplicates:function(){return this.withConstraint(new h),this},whenHandledThenExecute:function(a){if(!_.isFunction(a))throw"Value provided to 'whenHandledThenExecute' must be a function";return this.onHandled=a,this},withConstraint:function(a){if(!_.isFunction(a))throw"Predicate constraint must be a function";return this.constraints.push(a),this},withConstraints:function(a){var b=this;return _.isArray(a)&&_.each(a,function(a){b.withConstraint(a)}),b},withContext:function(a){return this.context=a,this},withDebounce:function(a){if(_.isNaN(a))throw"Milliseconds must be a number";var b=this.callback;return this.callback=_.debounce(b,a),this},withDelay:function(a){if(_.isNaN(a))throw"Milliseconds must be a number";var b=this.callback;return this.callback=function(c){setTimeout(b,a,c)},this},withPriority:function(a){if(_.isNaN(a))throw"Priority must be a number";return this.priority=a,this},withThrottle:function(a){if(_.isNaN(a))throw"Milliseconds must be a number";var b=this.callback;return this.callback=_.throttle(b,a),this}};var k={cache:{},compare:function(a,b){if(this.cache[b]&&this.cache[b][a])return!0;var c=new RegExp("^"+a.replace(/\./g,"\\.").replace(/\*/g,".*").replace(/#/g,"[A-Z,a-z,0-9]*")+"$"),d=c.test(b);return d&&(this.cache[b]||(this.cache[b]={}),this.cache[b][a]=!0),d}},l={subscriptions:{},wireTaps:new Array(0),publish:function(a,b){_.each(this.wireTaps,function(c){c(a,b)}),_.each(this.subscriptions[a.channel],function(c){_.each(c,function(c){n.configuration.resolver.compare(c.topic,a.topic)&&_.all(c.constraints,function(a){return a(b)})&&typeof c.callback=="function"&&(c.callback.apply(c.context,[b,a]),c.onHandled())})})},subscribe:function(a){var b,c,d,e=this.subscriptions[a.channel],f;e||(e=this.subscriptions[a.channel]={}),f=this.subscriptions[a.channel][a.topic],f||(f=this.subscriptions[a.channel][a.topic]=new Array(0)),b=f.length-1;for(;b>=0;b--)if(f[b].priority<=a.priority){f.splice(b+1,0,a),c=!0;break}return c||f.unshift(a),a},unsubscribe:function(a){if(this.subscriptions[a.channel][a.topic]){var b=this.subscriptions[a.channel][a.topic].length,c=0;for(;c<b;c++)if(this.subscriptions[a.channel][a.topic][c]===a){this.subscriptions[a.channel][a.topic].splice(c,1);break}}},addWireTap:function(a){var b=this;return b.wireTaps.push(a),function(){var c=b.wireTaps.indexOf(a);c!==-1&&b.wireTaps.splice(c,1)}}},m={2:function(a,b){a.channel||(a.channel=c),n.configuration.bus.publish(a,b)},3:function(a,b,c){n.configuration.bus.publish({channel:a,topic:b},c)}};l.subscriptions[f]={};var n={configuration:{bus:l,resolver:k},channel:function(a){var b=a.channel||c,d=a.topic;return new i(b,d)},subscribe:function(a){var b=a.callback,d=a.topic,e=a.channel||c;return new j(e,d,b)},publish:function(){var a=arguments.length;m[a]&&m[a].apply(this,arguments)},addWireTap:function(a){return this.configuration.bus.addWireTap(a)},linkChannels:function(a,b){var d=[];return _.isArray(a)||(a=[a]),_.isArray(b)||(b=[b]),_.each(a,function(a){var e=a.topic||"*";_.each(b,function(b){var e=b.channel||c;d.push(n.subscribe({channel:a.channel||c,topic:a.topic||"*",callback:function(a,c){var d=c;d.topic=_.isFunction(b.topic)?b.topic(c.topic):b.topic||c.topic,d.channel=e,n.publish(d,a)}}))})}),d}};a.postal=n})(window)
(function(a,b,c){typeof define=="function"&&define.amd?define(["underscore"],function(d){return c(d,a,b)}):c(a._,a,b)})(this,document,function(a,b,c,d){var e="/",f=50,g=0,h="postal",i=function(){},j=function(){var b;return function(c){var d=!1;return a.isString(c)?(d=c===b,b=c):(d=a.isEqual(c,b),b=a.clone(c)),!d}},k=function(a,b){this.channel=a,this.topic=b||""};k.prototype={subscribe:function(){var a=arguments.length;if(a===1)return new l(this.channel,this.topic,arguments[0]);if(a===2)return new l(this.channel,arguments[0],arguments[1])},publish:function(a,b){var c=b||{};c.channel=this.channel,c.timeStamp=new Date,c.topic=c.topic||this.topic,p.configuration.bus.publish(a,c)}};var l=function(a,b,c){this.channel=a,this.topic=b,this.callback=c,this.priority=f,this.constraints=new Array(0),this.maxCalls=g,this.onHandled=i,this.context=null,p.publish({event:"subscription.created",channel:a,topic:b},{channel:h,topic:"subscription.created"}),p.configuration.bus.subscribe(this)};l.prototype={unsubscribe:function(){p.configuration.bus.unsubscribe(this),p.publish({event:"subscription.removed",channel:this.channel,topic:this.topic},{channel:h,topic:"subscription.removed"})},defer:function(){var a=this.callback;return this.callback=function(b){setTimeout(a,0,b)},this},disposeAfter:function(b){if(a.isNaN(b)||b<=0)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var c=this.onHandled,d=a.after(b,a.bind(function(){this.unsubscribe(this)},this));return this.onHandled=function(){c.apply(this.context,arguments),d()},this},ignoreDuplicates:function(){return this.withConstraint(new j),this},whenHandledThenExecute:function(b){if(!a.isFunction(b))throw"Value provided to 'whenHandledThenExecute' must be a function";return this.onHandled=b,this},withConstraint:function(b){if(!a.isFunction(b))throw"Predicate constraint must be a function";return this.constraints.push(b),this},withConstraints:function(b){var c=this;return a.isArray(b)&&a.each(b,function(a){c.withConstraint(a)}),c},withContext:function(a){return this.context=a,this},withDebounce:function(b){if(a.isNaN(b))throw"Milliseconds must be a number";var c=this.callback;return this.callback=a.debounce(c,b),this},withDelay:function(b){if(a.isNaN(b))throw"Milliseconds must be a number";var c=this.callback;return this.callback=function(a){setTimeout(c,b,a)},this},withPriority:function(b){if(a.isNaN(b))throw"Priority must be a number";return this.priority=b,this},withThrottle:function(b){if(a.isNaN(b))throw"Milliseconds must be a number";var c=this.callback;return this.callback=a.throttle(c,b),this}};var m={cache:{},compare:function(a,b){if(this.cache[b]&&this.cache[b][a])return!0;var c=new RegExp("^"+a.replace(/\./g,"\\.").replace(/\*/g,".*").replace(/#/g,"[A-Z,a-z,0-9]*")+"$"),d=c.test(b);return d&&(this.cache[b]||(this.cache[b]={}),this.cache[b][a]=!0),d}},n={subscriptions:{},wireTaps:new Array(0),publish:function(b,c){a.each(this.wireTaps,function(a){a(b,c)}),a.each(this.subscriptions[c.channel],function(d){a.each(d,function(d){p.configuration.resolver.compare(d.topic,c.topic)&&a.all(d.constraints,function(a){return a(b)})&&typeof d.callback=="function"&&(d.callback.apply(d.context,[b,c]),d.onHandled())})})},subscribe:function(a){var b,c,d,e=this.subscriptions[a.channel],f;e||(e=this.subscriptions[a.channel]={}),f=this.subscriptions[a.channel][a.topic],f||(f=this.subscriptions[a.channel][a.topic]=new Array(0)),b=f.length-1;for(;b>=0;b--)if(f[b].priority<=a.priority){f.splice(b+1,0,a),c=!0;break}return c||f.unshift(a),a},unsubscribe:function(a){if(this.subscriptions[a.channel][a.topic]){var b=this.subscriptions[a.channel][a.topic].length,c=0;for(;c<b;c++)if(this.subscriptions[a.channel][a.topic][c]===a){this.subscriptions[a.channel][a.topic].splice(c,1);break}}},addWireTap:function(a){var b=this;return b.wireTaps.push(a),function(){var c=b.wireTaps.indexOf(a);c!==-1&&b.wireTaps.splice(c,1)}}},o={2:function(a,b){b.channel||(b.channel=e),p.configuration.bus.publish(a,b)},3:function(a,b,c){p.configuration.bus.publish(c,{channel:a,topic:b})}};n.subscriptions[h]={};var p={configuration:{bus:n,resolver:m},channel:function(a){var b=a.channel||e,c=a.topic;return new k(b,c)},subscribe:function(a){var b=a.callback,c=a.topic,d=a.channel||e;return new l(d,c,b)},publish:function(){var a=arguments.length;o[a]&&o[a].apply(this,arguments)},addWireTap:function(a){return this.configuration.bus.addWireTap(a)},linkChannels:function(b,c){var d=[];return a.isArray(b)||(b=[b]),a.isArray(c)||(c=[c]),a.each(b,function(b){var f=b.topic||"*";a.each(c,function(c){var f=c.channel||e;d.push(p.subscribe({channel:b.channel||e,topic:b.topic||"*",callback:function(b,d){var e=d;e.topic=a.isFunction(c.topic)?c.topic(d.topic):c.topic||d.topic,e.channel=f,p.publish(b,e)}}))})}),d}};return b.postal=p,p})

View file

@ -1,20 +1,21 @@
module.exports = function(postal) {
postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
module.exports = function(postal) {
// this returns a callback that, if invoked, removes the wireTap
return postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
};

View file

@ -1,4 +1,3 @@
var _ = require('underscore');
/*
postal.js
Author: Jim Cowart
@ -6,6 +5,8 @@ var _ = require('underscore');
Version 0.4.0
*/
var _ = require('underscore');
var DEFAULT_CHANNEL = "/",
DEFAULT_PRIORITY = 50,
DEFAULT_DISPOSEAFTER = 0,
@ -34,8 +35,14 @@ var ChannelDefinition = function(channelName, defaultTopic) {
};
ChannelDefinition.prototype = {
subscribe: function(callback) {
return new SubscriptionDefinition(this.channel, this.topic, callback);
subscribe: function() {
var len = arguments.length;
if(len === 1) {
return new SubscriptionDefinition(this.channel, this.topic, arguments[0]);
}
else if (len === 2) {
return new SubscriptionDefinition(this.channel, arguments[0], arguments[1]);
}
},
publish: function(data, envelope) {
@ -43,142 +50,140 @@ ChannelDefinition.prototype = {
env.channel = this.channel;
env.timeStamp = new Date();
env.topic = env.topic || this.topic;
postal.configuration.bus.publish(env, data);
postal.configuration.bus.publish(data, env);
}
};
var SubscriptionDefinition = function(channel, topic, callback) {
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
this.channel = channel;
this.topic = topic;
this.callback = callback;
this.priority = DEFAULT_PRIORITY;
this.constraints = new Array(0);
this.maxCalls = DEFAULT_DISPOSEAFTER;
this.onHandled = NO_OP;
this.context = null;
postal.publish({
event: "subscription.created",
channel: channel,
topic: topic
},{
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
});
postal.configuration.bus.subscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.created"
},
{
event: "subscription.created",
channel: channel,
topic: topic
});
};
SubscriptionDefinition.prototype = {
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
},
{
event: "subscription.removed",
channel: this.channel,
topic: this.topic
});
},
unsubscribe: function() {
postal.configuration.bus.unsubscribe(this);
postal.publish({
event: "subscription.removed",
channel: this.channel,
topic: this.topic
},{
channel: SYSTEM_CHANNEL,
topic: "subscription.removed"
});
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
defer: function() {
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn,0,data);
};
return this;
},
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
disposeAfter: function(maxCalls) {
if(_.isNaN(maxCalls) || maxCalls <= 0) {
throw "The value provided to disposeAfter (maxCalls) must be a number greater than zero.";
}
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
var fn = this.onHandled;
var dispose = _.after(maxCalls, _.bind(function() {
this.unsubscribe(this);
}, this));
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
this.onHandled = function() {
fn.apply(this.context, arguments);
dispose();
};
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
ignoreDuplicates: function() {
this.withConstraint(new DistinctPredicate());
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
whenHandledThenExecute: function(callback) {
if(! _.isFunction(callback)) {
throw "Value provided to 'whenHandledThenExecute' must be a function";
}
this.onHandled = callback;
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraint: function(predicate) {
if(! _.isFunction(predicate)) {
throw "Predicate constraint must be a function";
}
this.constraints.push(predicate);
return this;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withConstraints: function(predicates) {
var self = this;
if(_.isArray(predicates)) {
_.each(predicates, function(predicate) { self.withConstraint(predicate); } );
}
return self;
},
withContext: function(context) {
this.context = context;
return this;
},
withContext: function(context) {
this.context = context;
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDebounce: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.debounce(fn, milliseconds);
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withDelay: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = function(data) {
setTimeout(fn, milliseconds, data);
};
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withPriority: function(priority) {
if(_.isNaN(priority)) {
throw "Priority must be a number";
}
this.priority = priority;
return this;
},
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
withThrottle: function(milliseconds) {
if(_.isNaN(milliseconds)) {
throw "Milliseconds must be a number";
}
var fn = this.callback;
this.callback = _.throttle(fn, milliseconds);
return this;
}
};
var bindingsResolver = {
@ -209,9 +214,9 @@ var localBus = {
wireTaps: new Array(0),
publish: function(envelope, data) {
publish: function(data, envelope) {
_.each(this.wireTaps,function(tap) {
tap(envelope, data);
tap(data, envelope);
});
_.each(this.subscriptions[envelope.channel], function(topic) {
@ -279,14 +284,14 @@ var localBus = {
};
var publishPicker = {
"2" : function(envelope, payload) {
"2" : function(data, envelope) {
if(!envelope.channel) {
envelope.channel = DEFAULT_CHANNEL;
}
postal.configuration.bus.publish(envelope, payload);
postal.configuration.bus.publish(data, envelope);
},
"3" : function(channel, topic, payload) {
postal.configuration.bus.publish({ channel: channel, topic: topic }, payload);
postal.configuration.bus.publish(payload, { channel: channel, topic: topic });
}
};
@ -343,7 +348,7 @@ var postal = {
var newEnv = env;
newEnv.topic = _.isFunction(destination.topic) ? destination.topic(env.topic) : destination.topic || env.topic;
newEnv.channel = destChannel;
postal.publish(newEnv, msg);
postal.publish(msg, newEnv);
}
})
);
@ -352,5 +357,6 @@ var postal = {
return result;
}
};
module.exports = postal;

View file

@ -445,7 +445,6 @@ QUnit.specify("postal.js", function(){
assert(wireTapData[0].data).equals("I'm in yer bus, tappin' yer subscriptionz...");
});
it("wireTap envelope should match expected results", function() {
console.log("ONOES! " + JSON.stringify(wireTapEnvelope));
assert(wireTapEnvelope[0].channel).equals(DEFAULT_CHANNEL);
assert(wireTapEnvelope[0].topic).equals("Oh.Hai.There");
});

View file

@ -1,18 +1,33 @@
postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
(function(root, doc, factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["postal", "underscore"], function(postal, _) {
return factory(postal, _, root, doc);
});
} else {
// Browser globals
factory(root.postal, root._, root, doc);
}
}(this, document, function(postal, _, global, document, undefined) {
// this returns a callback that, if invoked, removes the wireTap
return postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
}));

View file

@ -0,0 +1,21 @@
module.exports = function(postal) {
// this returns a callback that, if invoked, removes the wireTap
return postal.addWireTap(function(data, envelope) {
var all = _.extend(envelope, { data: data });
if(!JSON) {
throw "This browser or environment does not provide JSON support";
}
try {
console.log(JSON.stringify(all));
}
catch(exception) {
try {
all.data = "ERROR: " + exception.message;
console.log(JSON.stringify(all));
}
catch(ex) {
console.log("Unable to parse data to JSON: " + exception);
}
}
});
};

View file

@ -1,5 +1,5 @@
var ChannelDefinition = function(channelName, defaultTopic) {
this.channel = channelName;
this.channel = channelName || DEFAULT_CHANNEL;
this.topic = defaultTopic || "";
};

View file

@ -2,5 +2,5 @@
postal.js
Author: Jim Cowart
License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license)
Version 0.4.0
Version 0.6.0
*/

View file

@ -1,8 +1,24 @@
//import("VersionHeader.js");
(function(root, doc, factory) {
if (typeof define === "function" && define.amd) {
// AMD. Register as an anonymous module.
define(["underscore"], function(_) {
return factory(_, root, doc);
});
} else {
// Browser globals
factory(root._, root, doc);
}
}(this, document, function(_, global, document, undefined) {
//import("Constants.js");
//import("DistinctPredicate.js");
//import("ChannelDefinition.js");
//import("SubscriptionDefinition.js");
//import("BindingsResolver.js");
//import("LocalBus.js");
//import("Api.js");
//import("Api.js");
global.postal = postal;
return postal;
}));

12
src/main/postal.node.js Normal file
View file

@ -0,0 +1,12 @@
//import("VersionHeader.js");
var _ = require('underscore');
//import("Constants.js");
//import("DistinctPredicate.js");
//import("ChannelDefinition.js");
//import("SubscriptionDefinition.js");
//import("BindingsResolver.js");
//import("LocalBus.js");
//import("Api.js");
module.exports = postal;