Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 8a86103f447c1c6a5b32dc3ad2f04da8cc196bd2 1 parent c09ef95
Stanislas Polu authored
View
3  .gitignore
@@ -0,0 +1,3 @@
+*~
+.DS_Store
+node_modules
View
0  README
No changes.
View
210 lib/base.js
@@ -0,0 +1,210 @@
+// Copyright Teleportd
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+/**
+ * fwk.js
+ *
+ * This is a repository of helper functions available directly from
+ * the pipes library object. These functions help adding methods to
+ * Crockford style objects, and adds a few functionalities to the
+ * Function, Array and String objects
+ *
+ * WARNING: never add methods to the Object type as they would appear
+ * in enumerations. The pipes fwk rely on the NON-EXISTENCE of such
+ * extended method on the Object type.
+ *
+ */
+
+var crypto = require('crypto');
+
+/**
+ * method(that, name, method, _super)
+ * Adds a method to the current object denoted by that and preserves
+ * _super implementation (see Crockford)
+ */
+exports.method = function(that, name, method, _super) {
+ if(_super) {
+ var m = that[name];
+ _super[name] = function() {
+ return m.apply(that, arguments);
+ };
+ }
+ that[name] = method;
+};
+
+/**
+ * getter(that, name, obj, prop)
+ * Generates a getter on the current object denoted by that
+ */
+exports.getter = function(that, name, obj, prop) {
+ var getter = function() {
+ return obj[prop];
+ };
+ that[name] = getter;
+};
+
+/**
+ * setter(that, name, obj, prop)
+ * Generates a setter on the current object denoted by that
+ */
+exports.setter = function(that, name, obj, prop) {
+ var setter = function (arg) {
+ obj[prop] = arg;
+ return that;
+ };
+ that['set' + name.substring(0, 1).toUpperCase() + name.substring(1)] = setter;
+};
+
+/**
+ * responds(that, name)
+ * Tests whether the object responds to a given function name
+ */
+exports.responds = function(that, name) {
+ return (that[name] && typeof that[name] === 'function');
+};
+
+/**
+ * once()
+ * Returns a function that will call the underlying function only once
+ * whether it is called once or multiple times
+ */
+Function.prototype.once = function() {
+ var fn = this;
+ var done = false;
+ return function() {
+ if(!done) {
+ args = Array.prototype.slice.call(arguments);
+ done = true;
+ fn.apply(null, args);
+ }
+ };
+};
+
+/**
+ * bind()
+ * The .bind method from Prototype.js
+ */
+Function.prototype.bind = function() {
+ var fn = this,
+ args = Array.prototype.slice.call(arguments),
+ object = args.shift();
+ return function(){
+ return fn.apply(
+ object,
+ args.concat(Array.prototype.slice.call(arguments))
+ );
+ };
+};
+
+/**
+ * remove(e)
+ * Removes the element e from the Array, using the JS '===' equality
+ */
+Array.prototype.remove = function(e) {
+ for(var i = 0; i < this.length; i++)
+ if(e === this[i]) this.splice(i, 1);
+};
+
+/**
+ * shallow(that)
+ * Shallow copy of the object that
+ */
+exports.shallow = function(that) {
+ if(that == null || typeof(that) != 'object')
+ return that;
+ var temp = new that.constructor();
+ for(var key in that) {
+ if(that.hasOwnProperty(key))
+ temp[key] = that[key];
+ }
+ return temp;
+};
+
+/**
+ * clone(that)
+ * Deep copy of the object that
+ */
+exports.clone = function(that) {
+ if(that == null || typeof(that) != 'object')
+ return this;
+ var temp = new that.constructor();
+ for(var key in that) {
+ if(that.hasOwnProperty(key))
+ temp[key] = clone(that[key]);
+ }
+ return temp;
+};
+
+/**
+ * mkhash(that)
+ * Generates a 'deep' hash that ignores properties starting with a '_'
+ */
+exports.mkhash = function(that) {
+ var hash = crypto.createHash('sha1');
+ for(var i in that) {
+ if(i.charAt(0) !== '_' && that.hasOwnProperty(i)) {
+ var str = JSON.stringify(that[i]);
+ if(str)
+ hash.update(str);
+ }
+ }
+ /** add args to update */
+ for(var j = 1; j < arguments.length; j++)
+ hash.update(arguments[j]);
+ return hash.digest(encoding='hex');
+};
+
+/**
+ * forEach(that, fun)
+ * Applies Array-like forEach to an object
+ */
+exports.forEach = function(that, fun /*, thisp */) {
+ "use strict";
+
+ if(that === void 0 || that === null)
+ throw new TypeError();
+
+ var t = Object(that);
+
+ if(typeof fun !== "function")
+ throw new TypeError();
+
+ var thisp = arguments[2];
+ for(var i in t) {
+ if(t.hasOwnProperty(i)) {
+ fun.call(thisp, t[i], i, t);
+ }
+ }
+};
+
+/**
+ * trim() ltrim() rtrim()
+ * String trim functions
+ */
+String.prototype.trim = function() {
+ return this.replace(/^\s+|\s+$/g,"");
+};
+String.prototype.ltrim = function() {
+ return this.replace(/^\s+/,"");
+};
+String.prototype.rtrim = function() {
+ return this.replace(/\s+$/,"");
+};
View
42 lib/fwk.js
@@ -0,0 +1,42 @@
+// Copyright Teleportd
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+/**
+ * Top-Level fwk Library
+ */
+
+var base = require("./base.js");
+var lock = require("./lock.js");
+var mplex = require("./mplex.js");
+
+exports.method = base.method;
+exports.getter = base.getter;
+exports.setter = base.setter;
+exports.responds = base.responds;
+exports.shallow = base.shallow;
+exports.clone = base.clone;
+exports.makehash = base.makehash;
+exports.forEach = base.forEach;
+
+exports.lock = lock.lock;
+
+exports.mplex = mplex.mplex;
+
View
122 lib/lock.js
@@ -0,0 +1,122 @@
+// Copyright Teleportd
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var util = require('util');
+var events = require('events');
+var base = require("./base.js");
+
+/**
+ * lock.js
+ *
+ * A lock implementation for javascript, useful in some precise case where
+ * multiple asynchronous events or callbacks should be ordered.
+ * Each lock is in fact a collection of locks based on the tags passed.
+ */
+
+/**
+ * A Lock
+ *
+ * @extends events.EventEmitter
+ *
+ * @param spec {}
+ */
+var lock = function(spec, my) {
+ my = my || {};
+ var _super = {};
+
+ my.wlock = {};
+ my.rlock = {};
+
+ var that = new events.EventEmitter();
+ that.setMaxListeners(0);
+
+
+ // public
+ var rlock; /* rlock: acquires a read lock */
+ var wlock; /* wlock: acquires a write lock */
+
+ /**
+ * rlock(tag, function(unlock) {... unlock(); });
+ * acquires a read lock then executes section
+ */
+ rlock = function(tag, section_) {
+ if(!my.wlock[tag]) {
+ if(!my.rlock[tag]) my.rlock[tag] = 0;
+ my.rlock[tag]++;
+
+ var unlock = function() {
+ //util.debug('READ UNLOCK: ' + tag);
+ process.nextTick(
+ function() {
+ my.rlock[tag]--;
+ if(my.rlock[tag] < 0) {
+ my.rlock[tag] = 0;
+ util.debug('WARNING: lock.js rlock < 0 for ' + tag);
+ }
+ that.emit(tag);
+ });
+ };
+ /** read critical section */
+ //util.debug('READ CRITICAL: ' + tag);
+ section_(unlock);
+ }
+ else {
+ that.once(tag, function() { rlock(tag, section_); });
+ }
+ };
+
+ /**
+ * wlock(tag, function(unlock) {... unlock(); });
+ * acquires a write lock then executes section
+ */
+ wlock = function(tag, section_) {
+ if(!my.rlock[tag] && !my.wlock[tag]) {
+ my.wlock[tag] = 1;
+
+ var unlock = function() {
+ //util.debug('WRITE UNLOCK: ' + tag);
+ process.nextTick(
+ function() {
+ my.wlock[tag]--;
+ if(my.wlock[tag] !== 0) {
+ my.wlock[tag] = 0;
+ util.debug('WARNING: lock.js wlock !== 0 for ' + tag);
+ }
+ that.emit(tag);
+ });
+ };
+ /** write critical section */
+ //util.debug('WRITE CRITICAL: ' + tag);
+ section_(unlock);
+ }
+ else {
+ that.once(tag, function() { wlock(tag, section_); });
+ }
+ };
+
+
+ base.method(that, 'rlock', rlock);
+ base.method(that, 'wlock', wlock);
+
+ return that;
+};
+
+exports.lock = lock;
View
112 lib/mplex.js
@@ -0,0 +1,112 @@
+// Copyright Stanislas Polu
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var util = require('util');
+var base = require("./base.js");
+
+/**
+ * mplex.js
+ *
+ * The mplex object allows to wait for k asynchronous operations before executing
+ * a completion callback with a lightweight syntax
+ *
+ * Example:
+ * ===================================================
+ * var mplex = fwk.mplex({});
+ *
+ * for(...) {
+ * (function(htag, cb) {
+ * my.pipe.send(fwk.message({})
+ * .setType('2w')
+ * .setSubject('IOIDXD:SEARCH')
+ * .addTarget(htag)
+ * .setBody(q.json()),
+ * function(err, hdr, res) {
+ * ...
+ * cb();
+ * });
+ * }(htag, mplex.callback()));
+ * }
+ *
+ * mplex.go(function() {
+ * pump(now, pos + mod, mod * 2);
+ * });
+ * ====================================================
+ */
+
+/**
+ * A MPlex is an object that allows to trigger n callback functions and
+ * get one callback only when all these functions have returned
+ *
+ * @extends {}
+ *
+ * @param spec {}
+ */
+var mplex = function(spec, my) {
+ my = my || {};
+ var _super = {};
+
+ var that = {};
+
+ my.cb = function() {};
+
+ my.done = 0; // number of callbacks done
+ my.wait = 0; // number of callbacks waiting
+ my.go = false; // started?
+ my.cbargs = [];
+
+ // public
+ var callback; /* callback() returns a callback to wait on */
+ var go; /* go(cb) start waiting for generated callbacks */
+
+ /* callback()
+ * returns a callback to wait on */
+ callback = function() {
+ my.wait ++;
+ return function() {
+ my.cbargs.push(arguments);
+ my.wait --;
+ my.done ++;
+ if(my.wait === 0 && my.go)
+ my.cb();
+ };
+ };
+
+ /* go(cb)
+ * start waiting for generated callbacks */
+ go = function(cb) {
+ if(cb === null || typeof cb === "undefined")
+ throw new TypeError();
+ my.cb = cb;
+ my.go = true;
+ if(my.wait === 0) {
+ my.cb();
+ }
+ };
+
+ base.method(that, 'callback', callback);
+ base.method(that, 'go', go);
+ base.getter(that, 'cbargs', my, 'cbargs');
+
+ return that;
+};
+
+exports.mplex = mplex;
View
17 package.json
@@ -0,0 +1,17 @@
+{
+ "name": "fwk",
+ "version": "0.1.0",
+ "description": "Simple JS framework for node.js",
+ "keywords": ["fwk", "node"],
+ "homepage": "https://github.com/teleportd/fwk",
+ "author": { "name": "Stanislas Polu",
+ "email": "stan@teleportd.com",
+ "url": "http://twitter.com/spolu" },
+ "repository" : { "type" : "git",
+ "url" : "http://github.com/teleportd/fwk.git" },
+ "os" : [ "linux",
+ "darwin",
+ "freebsd" ],
+ "main" : "./lib/fwk",
+ "engines" : { "node" : ">=0.4.0" }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.