Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

harcon

Package Overview
Dependencies
Maintainers
1
Versions
326
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

harcon - npm Package Compare versions

Comparing version 0.9.6 to 0.9.8

test/components/claire.js

6

lib/Barrel.js

@@ -33,3 +33,3 @@ var async = require('async');

if(this.systemFirestarter){
var args = [ this.systemFirestarter.name + '.' + arguments[0] ];
var args = [ this.systemFirestarter.division, this.systemFirestarter.name + '.' + arguments[0] ];
for(var i=1; i<arguments.length; i+=1)

@@ -88,3 +88,3 @@ args.push( arguments[i] );

self.firestarters.forEach( function( fs ){
if( (comm.source === fs.name) || (fs.listeningToResponses && fs.matches( comm.event ) ) ){
if( (comm.source === fs.name) || (fs.listeningToResponses && fs.matches( comm.division, comm.event ) ) ){
fs.appease( err, comm, responseComms );

@@ -104,3 +104,3 @@ }

var matching = this.firestarters.filter( function( fs ){ return fs.matches( comm.event ); } );
var matching = this.firestarters.filter( function( fs ){ return fs.matches( comm.division, comm.event ); } );

@@ -107,0 +107,0 @@ if( matching.length === 0 ){

@@ -11,3 +11,3 @@ var Cerobee = require('clerobee');

*/
function Communication(originalId, flowId, externalId, source, event, params, callback, target, error, response){
function Communication(originalId, flowId, externalId, division, source, event, params, callback, target, error, response){
this.id = clerobee.generate();

@@ -25,2 +25,4 @@ this.originalId = originalId || this.id;

this.division = division || '';
this.params = params || [];

@@ -75,3 +77,3 @@

commPrototype.spread = function( ) {
var comm = new Communication( this.originalId, this.flowId, this.externalId, this.source, this.event, this.params );
var comm = new Communication( this.originalId, this.flowId, this.externalId, this.division, this.source, this.event, this.params );
comm.id = this.id;

@@ -93,3 +95,3 @@ comm.date = this.date;

commPrototype.twist = function( name, error, response ) {
var comm = new Communication( this.id, this.flowId, this.externalId, this.source, this.event, this.params, this.callback, name, error, response );
var comm = new Communication( this.id, this.flowId, this.externalId, this.division, this.source, this.event, this.params, this.callback, name, error, response );
return comm;

@@ -108,3 +110,3 @@ };

commPrototype.burst = function( name, event, params, callback ) {
var comm = new Communication( null, this.flowId, this.externalId, name, event, params, callback );
var comm = new Communication( null, this.flowId, this.externalId, this.division, name, event, params, callback );
return comm;

@@ -130,4 +132,4 @@ };

};
exports.newCommunication = function( originalId, flowId, externalId, source, event, params, callback, target, error, response ){
return new Communication( originalId, flowId, externalId, source, event, params, callback, target, error, response );
exports.newCommunication = function( originalId, flowId, externalId, division, source, event, params, callback, target, error, response ){
return new Communication( originalId, flowId, externalId, division, source, event, params, callback, target, error, response );
};

@@ -18,3 +18,4 @@ var Communication = require('./Communication');

*/
function Firestarter( ){
function Firestarter( division ){
this.division = division || '';
}

@@ -33,2 +34,16 @@

/**
* Validates division of an incoming message
*/
firestarter.sameDivision = function( division ){
if( !this.divisionPath )
this.divisionPath = this.division.split('.');
var dPath = division.split('.'), i = 0;
for( i=0; i<this.divisionPath.length; i+=1 ){
if( i >= dPath.length || this.divisionPath[i] !== dPath[i] ) return false;
}
return true;
};
/**
* Matches the emited event with the interest of the entity encapsulated by this firestarter

@@ -40,3 +55,3 @@ *

*/
firestarter.matches = function( eventName ){
firestarter.matches = function( division, eventName ){
throw new Error('To be implemented...');

@@ -138,8 +153,10 @@ };

firestarter.simpleIgnite = function( ){
var event = arguments[ 0 ];
var self = this;
var division = arguments[ 0 ];
var event = arguments[ 1 ];
var hasCallback = isFunction( arguments[ arguments.length-1 ] );
var params = [].slice.call(arguments, 1, hasCallback ? arguments.length-1 : arguments.length );
var params = self.sliceArguments.apply( self, arguments ).slice( 2, hasCallback ? arguments.length-1 : arguments.length );
var callback = hasCallback ? arguments[ arguments.length-1 ] : null;
var comm = Communication.newCommunication( null, null, null, this.name, event, params, callback );
var comm = Communication.newCommunication( null, null, null, division, this.name, event, params, callback );

@@ -162,3 +179,5 @@ this.logger.harconlog(null, 'Initiate ignition', {comm: comm} );

firestarter.ignite = function( ){
var event = arguments[ 0 ];
var self = this;
var division = arguments[ 0 ];
var event = arguments[ 1 ];
if( isString(event) )

@@ -171,3 +190,3 @@ return this.simpleIgnite.apply( this, arguments );

event.forEach( function(ev){
var args = [ev].concat( arguments.slice( 1 ) );
var args = [division, ev].concat( self.sliceArguments.apply( self, arguments ).slice( 2 ) );
ids.push( this.simpleIgnite.apply( this, args ) );

@@ -189,5 +208,6 @@ } );

firestarter.burst = function( comm, params ){
var self = this;
var event = params[ 0 ];
var hasCallback = params.length>0 && isFunction( params[ params.length-1 ] );
var call_params = [].slice.call(params, 1, hasCallback ? params.length-1 : params.length );
var call_params = self.sliceArguments.apply( self, arguments ).slice( 1, hasCallback ? params.length-1 : params.length );
var callback = hasCallback ? params[ params.length-1 ] : null;

@@ -194,0 +214,0 @@

@@ -20,5 +20,7 @@ var Firestarter = require('./Firestarter');

*/
function Firestormstarter( barrel, object, logger ){
function Firestormstarter( barrel, division, object, logger ){
var self = this;
this.division = division || '';
this.name = object.name || 'Unknown flames';

@@ -34,3 +36,4 @@

this.object.ignite = function(){
self.ignite.apply( self, arguments );
var args = [ self.division ].concat( self.sliceArguments.apply( self, arguments ) );
self.ignite.apply( self, args );
};

@@ -50,6 +53,8 @@ this.logger = logger;

firestorm.matches = function( eventName ){
firestorm.matches = function( division, eventName ){
if( !this.sameDivision( division ) ) return false;
var index = eventName.lastIndexOf( '.' );
if( index === -1 ){ index = eventName.length; }
var matches = index === -1 ? this.events.contains(eventName) : ( this.context === eventName.substring(0,index) && this.events.contains(eventName.substring(index+1) ) );
var matches = this.context === eventName.substring(0,index) && this.events.contains(eventName.substring(index+1) );

@@ -56,0 +61,0 @@ this.logger.harconlog( null, 'Matching', {events: this.events, eventName: eventName, matches: matches}, 'silly' );

@@ -21,3 +21,3 @@ var Communication = require('./Communication');

*/
function Flamestarter( barrel, name, eventName, fn, logger ){
function Flamestarter( barrel, division, name, eventName, fn, logger ){
this.isRegex = isRegExp( eventName );

@@ -30,2 +30,3 @@ this.isString = isString( eventName );

this.barrel = barrel;
this.division = division || '';
this.name = name;

@@ -67,3 +68,5 @@ this.event = eventName;

flamestarter.matches = function( eventName ){
flamestarter.matches = function( division, eventName ){
if( !this.sameDivision( division ) ) return false;
var matches = this.innerMatches( eventName );

@@ -70,0 +73,0 @@

@@ -30,3 +30,3 @@ var Communication = require('../lib/Communication');

/**
* Main control point of the messaging subsystem
* Main control point of the messaging system
*

@@ -41,2 +41,4 @@ * @class Inflicter

this.division = '';
var self = this;

@@ -56,2 +58,10 @@

this.sliceArguments = function( ){
var args = new Array(arguments.length);
for(var i = 0; i < args.length; i+=1) {
args[i] = arguments[i];
}
return args;
};
this.systemFirestarter = this.barrel.systemFirestarter = this.addicts( {

@@ -62,6 +72,8 @@ name: self.name,

logger: self.logger,
division: self.division,
context: self.context,
detracts: self.detracts,
addicts: self.addicts,
addict: self.addict
addict: self.addict,
sliceArguments: self.sliceArguments
} );

@@ -100,3 +112,4 @@ }

object.inflicterContext = this.inflicterContext;
var fss = new Firestormstarter( this.barrel, object, this.logger );
var fss = new Firestormstarter( this.barrel, object.division || this.division, object, this.logger );
fss.sliceArguments = this.sliceArguments;

@@ -124,4 +137,5 @@ if( object.init ){

*/
inflicter.addict = function( name, eventName, fn ){
var flamestarter = new Flamestarter( this.barrel, name, eventName, fn, this.logger );
inflicter.addict = function( name, eventName, fn, division ){
var flamestarter = new Flamestarter( this.barrel, division || this.division, name, eventName, fn, this.logger );
flamestarter.sliceArguments = this.sliceArguments;

@@ -128,0 +142,0 @@ return this.barrel.affiliate( flamestarter );

{
"name": "harcon",
"version": "0.9.6",
"version": "0.9.8",
"description": "Messaging/Service Bus for the harmonic convergence of node-based enterprise entities.",

@@ -48,3 +48,3 @@ "keywords": [

},
"_id": "harcon@0.9.6"
"_id": "harcon@0.9.8"
}

@@ -7,3 +7,3 @@ Harcon - Messaging/Service Bus for the harmonic convergence of node-based enterprise entities or in-browser communication between web components

========
[harcon](https://github.com/imrefazekas/harcon) is a enterprise-level service bus for NodeJS/Browser giving high abstraction layer for interoperability between entities in a highly structured and fragmented ecosystem.
[harcon](https://github.com/imrefazekas/harcon) is a enterprise-level service bus for NodeJS/Browser giving superior abstraction layer for interoperability between entities in a highly structured and fragmented ecosystem. It allows you to design and implement complex workflows where context and causality of messages are important.

@@ -28,3 +28,3 @@ The library has a stunning feature list beyond basic messaging functionality.

__!Note__: Harcon's concept is to introduce a clean and high abstraction layer over messaging between entities. Like in case of every abstraction tool, for simple webapps or plain REST services, it can be proven as a liability.
__!Note__: Harcon's concept is to introduce a clean and high abstraction layer over messaging between entities. Like in case of every abstraction tool, for webapps which are simple as 1, it can be proven as a liability.

@@ -36,39 +36,185 @@ __!Note__: To use in browser, a CommonJS-enabled packager has to be applied like [browserify](http://browserify.org) or [webpack](http://webpack.github.io).

# Installation
## Installation
$ npm install harcon
## Features:
... to be filled
## Quick setup
```javascript
var Inflicter = require('Inflicter');
var inflicter = new Inflicter( );
var Inflicter = require('Inflicter');
var inflicter = new Inflicter( );
// define a listener function listening every message withing the context "greet"
inflicter.addict('peter', 'greet.*', function(greetings1, greetings2, callback){
callback(null, 'Hi there!');
} );
// define a listener function listening every message withing the context "greet"
inflicter.addict('peter', 'greet.*', function(greetings1, greetings2, callback){
callback(null, 'Hi there!');
} );
// define an plain object serving as listener withing the context "greet" to messages "warm"
marie = {
name: 'marie',
context: 'greet',
warm: function(greetings1, greetings2, callback){
callback( null, 'Bonjour!' );
}
};
inflicter.addicts( marie );
// define an plain object serving as listener withing the context "greet" to messages "warm"
marie = {
name: 'marie',
context: 'greet',
warm: function(greetings1, greetings2, callback){
callback( null, 'Bonjour!' );
}
};
inflicter.addicts( marie );
// sends a communication 'greet.everyone' with parameters and defines a callback to handle responses
// will receive back 2 answers: 'Hi there!' and 'Bonjour!'
inflicter.ignite( 'greet.everyone', 'Whatsup?', 'How do you do?', function(err, res){
console.log( err, res );
} );
```
[Back to Feature list](#features)
// sends a communication 'greet.everyone' with parameters and defines a callback to handle responses
// will receive back 2 answers: 'Hi there!' and 'Bonjour!'
inflicter.ignite( 'greet.everyone', 'Whatsup?', 'How do you do?', function(err, res){
console.log( err, res );
} );
## Workflows
[Back to Feature list](#features)
In an enterprise-level system, one has to realize complex communication structure where lots of entities are following business logic and rules, involving subsystems and external resources, policies and other considerations, in short form: workflows.
I take the liberty to define the workflow now as well defined routes and causality of messages.
Simple method calls do the same, you can say. Yes and no.
In a workflow, you are not dependent on the response timeframe, workflows manage distance in time and space. The recepient of a message can be on another server or city or planet. Recepient can answer right away or tomorrow or never.
Let me show a very short example:
You are a company providing VPN services to customers.
Orders taken by agents go to some accounting and client management subsystem and eventually your subsystem dealing with the technical setup receives a request through an interface of yours.
Next step is to identify the network the user will be connected to, so a message is sent to the networking department who will respond maybe a day later. When it does, you have to continue your workflow where it is stopped, so you try to allocate network resources there and if it is successful you create a network configuration firmware to be used on the client's router to communicate with your backbone. When it is done by a config creator submodule of yours, you send it to an operation department for testing and when it is done you send back the results to the accounting for validation.
And of course everything must be traceable and reconstructable and maybe rollable backwards.
This is an extremely simplified use case, in real-life, workflows are much more complicated things and even harder to handle properly.
[harcon](https://github.com/imrefazekas/harcon) is not a workflow designer tool, __"just"__ a low-level library to manage such processes. You define entities and the communications among them then publish them.
You can resurrect a workflow if it failed and continue where it failed.
You have to understand some details to use this lib at full scale.
#### Entities
One can define 2 type of entities:
- simple function: when you associate a function with an event-pattern. Recommended to be used as observer, job-like, surveillance-, or interface-related asset.
```javascript
// Qualified name - will answer to only this message
inflicter.addict('hugh', 'allocate.ip', function(callback){
callback(null, 'Done.');
} );
// Wildcards - will answer anything within the context greet
inflicter.addict('peter', 'greet.*', function(callback){
callback(null, 'Done.');
} );
// Regular expression - will answer anything where message name start with string 'job'
inflicter.addict('john', /job.*/, function(callback){
callback(null, 'Done.');
} );
```
- objects: service object enclosing service functions as a unique and complete context. Recommended to be used as business entities.
```javascript
var bookKeeper = {
name: 'BookKeeper',
context: 'booking',
newOrder: function( customer, callback ){
callback( null, 'Done.' );
},
ordersOfToday: function( callback ){
callback( null, [] );
}
};
...
inflicter.ignite( 'booking.newOrder', {name: 'Stephen', customerID:123}, function(err, res){
console.log( 'Finished', err, res );
} );
inflicter.ignite( 'booking.ordersOfToday', function(err, res){
console.log( 'Finished', err, res );
} );
```
The name of every entity must be unique. Entities belong to a context as defined above. A context might be associatd to multiple entities depending on you orchestration.
Every function within an entity will be considered as service and can be called using the 'context' + 'functionName' pair.
#### Chain messages
To chain messages, define the next point in the workflow you have to add another parameter to your service function:
```javascript
var order = {
name: 'Order',
context: 'order',
newVPN: function( customer, ignite, callback ){
ignite( 'allocate.address', '127.0.0.1', function(err, res){
callback(err, res);
} );
}
};
...
inflicter.ignite( 'order.newVPN', {name: 'Stephen', customerID:123}, function(err, res){
console.log( 'Finished', err, res );
} );
```
That will initiate a small workflow. __inflicter.ignite__ send a message to entity Order who will send within the same workflow to the Allocator. When it answeres, then the message of the beginning will be answered. [harcon](https://github.com/imrefazekas/harcon) will know if you initiate a message within the processing of another one and considers it as part of the ongoing workflow and tracks it.
Mind the async execution to keep everything in track!
#### Call back or not?
You are not forced to always send answer, in some cases a quite entities is desired. If you do not define a callback neither side of the communication, [harcon](https://github.com/imrefazekas/harcon) will consider it as a one-ways message sending.
```javascript
// Qualified name - will answer to only this message
inflicter.addict('karl', 'reserve.address', function( address ){
// Do something...
} );
...
inflicter.ignite( 'reserve.address', '127.0.0.1' );
```
#### Entity initialization
The need to pass contextual parameters to entities might rise. The options object passed to the constructure of Inflicter allows you to specify parameters for entities which will be passed while the init method defined in the entity is called.
```javascript
inflicter = new Inflicter( { /* ... */ marie: {greetings: 'Hi!'} } );
var marie = {
name: 'marie',
context: 'test',
init: function (options) {
// {greetings: 'Hi!'} will be passed
}
// services ...
};
```
#### Logging
When you create the Inflicter instance, you can pass a logger object which will be respected and used to do loggings. If not set, [harcon](https://github.com/imrefazekas/harcon) will log everything to the console. So in production, setting up a logging facility ( like [winston](https://github.com/flatiron/winston) or [bunyan](https://github.com/trentm/node-bunyan) ) is strongly adviced.
```javascript
inflicter = new Inflicter( { logger: logger /* ... */ } );
```
#### Unique messages
Every communication exchanged possesses the following properties (not exclusively):
- unique ID
- reference to the parent message if exists
- uniqued ID of the workflow itself
- external ID of the workflow started by an external communication involving a reference number to consider
- timestamp
Any time you sends a message or receives an answer, such objects are bypassing through the harcon system which logs and tracks all of them.
By default, [harcon](https://github.com/imrefazekas/harcon) uses 32 as length of the IDs which are unique over time and among computer nodes. You can override this default when initiating Inflicter
```javascript
inflicter = new Inflicter( { /* ... */ idLength: 32 } );
```
## Extension
[harcon](https://github.com/imrefazekas/harcon) can be easily extended by using pure harcon components listening to system events:
```javascript
var extension = {
name: 'As you design it',
context: inflicter.name,
castOf: function( name, firestarter ){
},
affiliate: function( firestarter ){
},
close: function(){
}
}
inflicter.addicts( extension );
```
In the current version, the inflicter instance you are using will send to your components events about system closing, entity publishing and revoking. For a working example, please check [harcon-radiation](https://github.com/imrefazekas/harcon-radiation).
## License

@@ -75,0 +221,0 @@

module.exports = {
name: 'marie',
context: 'greet',
init: function( options ){
console.log('Init...', options);
},
// Simple service function listening to the morning.simple message where morning comes from context and simple is identified by the name of the fuction.
simple: function(greetings1, greetings2, callback){
this.greetings = [ greetings1, greetings2 ];
callback( null, 'Bonjour!' );
init: function (options) {
console.log('Init...', options);
},
// Simple service function listening to the greet.simple message where greet comes from context and simple is identified by the name of the fuction.
simple: function (greetings1, greetings2, callback) {
this.greetings = [greetings1, greetings2];
callback(null, 'Bonjour!');
}
};

@@ -45,3 +45,3 @@ var chai = require("chai");

// Sending a greetings message with 2 parameters and waiting for the proper answer
inflicter.ignite( 'greet.simple', 'whatsup?', 'how do you do?', function(err, res){
inflicter.ignite( '', 'greet.simple', 'whatsup?', 'how do you do?', function(err, res){
console.log( err, res );

@@ -60,3 +60,3 @@ should.not.exist(err); should.exist(res);

// Sending a morning message and waiting for the proper answer
inflicter.ignite( 'morning.wakeup', function(err, res){
inflicter.ignite( '', 'morning.wakeup', function(err, res){
console.log( err, res );

@@ -72,3 +72,3 @@

// Sending a morning message and waiting for the proper answer
inflicter.ignite( 'cave.echo', function(err, res){
inflicter.ignite( '', 'cave.echo', function(err, res){
console.log( err, res );

@@ -75,0 +75,0 @@

var Inflicter = require('../lib/Inflicter');
var inflicter = new Inflicter( { logger: { file: 'test.log', level: 'debug' }, idLength: 32 } );
var inflicter = new Inflicter( { idLength: 32 } );

@@ -13,2 +13,9 @@ var claire = {

var claireFS = inflicter.addicts( claire );
setTimeout( function(){
inflicter.ignite( '', 'dire.bonjour', function(err, res){
console.log( '::::::::::::', err, res );
} );
}, 1000);
/*
var marie = {

@@ -24,4 +31,4 @@ name: 'marie',

};
var marieFS = inflicter.addicts( marie );
var marieFS = inflicter.addicts( marie );*/
/*
var julie = {

@@ -36,3 +43,3 @@ name: 'julie',

};
var julieFS = inflicter.addicts( julie );
var julieFS = inflicter.addicts( julie );*/
/*

@@ -42,3 +49,3 @@ inflicter.ignite( 'morning.wakeup', function(err, res){

} );*/
/*
var karl = {

@@ -54,3 +61,3 @@ name: 'karl',

var karlFS = inflicter.addicts( karl );
karl.enter();
karl.enter();*/

@@ -74,2 +81,4 @@ /*

*/
//setTimeout( function(){ console.log(':::', inflicter.listeners()); }, 1000);
setTimeout( function(){ inflicter.close(); }, 2000);

@@ -5,2 +5,6 @@ var winston = require('winston');

options = options || {};
if( options.console ){
return new (winston.Logger)({ transports: [ new (winston.transports.Console)({ colorize: 'true' }) ] });
}
if( options.exceptionFile )

@@ -7,0 +11,0 @@ winston.handleExceptions(new winston.transports.File({ filename: options.exceptionFile }));

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc