Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

doublescore

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

doublescore - npm Package Compare versions

Comparing version
0.2.1
to
0.3.0
+39
lib/clone.js
'use strict';
var Types = require( './types' );
var cloneDepth = 0;
exports.clone = function( arg ) {
cloneDepth++;
if ( cloneDepth >= 100 ) {
cloneDepth = 0;
throw new Error( 'max clone depth of 100 reached' );
}
var target = null;
if ( arg instanceof Date ) {
target = new Date( arg.toISOString() );
} else if ( Types.isArray( arg ) ) {
target = [];
for ( var i = 0; i < arg.length; i++ ) {
target[ i ] = exports.clone( arg[ i ] );
}
} else if ( Types.isObject( arg ) ) {
target = {};
for ( var field in arg ) {
if ( arg.hasOwnProperty( field ) ) {
target[ field ] = exports.clone( arg[ field ] );
}
}
} else { // functions, etc. not cloneable, and will pass through, though for primitives like strings and numbers, arg is cloning
target = arg;
}
cloneDepth--;
return target;
};
'use strict';
var Mixin = require( './mixin' );
var Close = module.exports = {
close: function( params ) {
params = Mixin.mixin( {
max: 1,
maxException: false,
ttl: 30000
}, params );
return function( cb ) {
var calls = 0;
var timeout = null;
if ( params.ttl && params.ttl > 0 ) {
timeout = setTimeout( function() {
calls++;
timeout = null;
setImmediate( cb, new Error( 'timeout' ) );
}, params.ttl );
}
return function( err, data ) {
calls++;
if ( params.max > -1 && calls > params.max ) {
if ( params.maxException ) {
throw new Error( 'max callbacks ' + params.max );
}
return false;
}
if ( timeout ) {
clearTimeout( timeout );
timeout = null;
}
if ( err ) {
cb( err );
} else if ( arguments.length > 1 ) {
cb( null, data );
} else {
cb( null );
}
return true;
};
};
}
};
'use strict';
var Clone = require( './clone' );
var Types = require( './types' );
var mixinDepth = 0;
exports.mixin = function( arg ) {
mixinDepth++;
if ( mixinDepth >= 100 ) {
mixinDepth = 0;
throw new Error( 'max mixin depth of 100 reached' );
}
var target = Clone.clone( arg ); // clone so we don't modify the original
// handle arbitrary number of mixins. precedence is from last to first item passed in.
for ( var i = 1; i < arguments.length; i++ ) {
var source = arguments[ i ];
// mixin the source differently depending on what is in the destination
switch ( Types.getType( target ) ) {
case 'object':
case 'array':
case 'function':
// mixin in the source differently depending on its type
switch ( Types.getType( source ) ) {
case 'array':
case 'object':
case 'function':
// we don't care what descendant of object the source is
for ( var field in source ) {
// don't mixin parent fields
if ( source.hasOwnProperty( field ) ) {
// if the target is an array, only take fields that are integers
if ( Types.isArray( target ) ) {
var fieldFloat = parseFloat( field );
// the field started with a number, or no number at all, then had non-numeric characters
if ( isNaN( fieldFloat ) || fieldFloat.toString().length !== field.length || Types.getType( fieldFloat ) !== 'integer' ) {
continue;
}
}
// recurse mixin differently depending on what the target value is
switch ( Types.getType( target[ field ] ) ) {
// for any non-objects, do this
case 'undefined':
case 'null':
switch ( Types.getType( source[ field ] ) ) {
case 'undefined':
// NO-OP undefined doesn't override anything
break;
case 'null':
target[ field ] = null;
break;
default:
target[ field ] = Clone.clone( source[ field ] );
break;
}
break;
// if the target is already an object, we can mixin on it
default:
target[ field ] = exports.mixin( target[ field ], source[ field ] );
break;
}
}
}
break;
default:
// NO-OP, primitives can't mixin to objects, arrays and functions
break;
}
break;
default:
// mixin in the source differently depending on its type
switch ( Types.getType( source ) ) {
// arrays and objects just replace primitives
case 'array':
case 'object':
// override primitives by just passing through a clone of parent
target = Clone.clone( source );
break;
default:
// target is a primitive and can't be null or undefined here, and all other primitives have equal precedence, so just pass through
target = source;
break;
}
break;
}
}
mixinDepth--;
return target;
};
'use strict';
exports.timer = function() {
// account for overhead within this function, this may not be a good idea
var offset = 1;
var start = new Date().getTime() + offset;
return function( reset ) {
var diff = new Date().getTime() - start;
if ( diff < 0 ) {
diff = 0;
}
if ( reset ) {
start = new Date().getTime() + offset;
}
return diff;
};
};
'use strict';
var myArray = Array;
if ( !myArray.isArray ) {
myArray = {
isArray: function( arg ) {
return Object.prototype.toString.call( arg ) === '[object Array]';
}
};
}
var Types = module.exports = {
isArray: function( arg ) {
return myArray.isArray( arg );
},
isNumber: function( arg ) {
return typeof arg === 'number' && !isNaN( arg );
},
isObject: function( arg ) {
return typeof arg === 'object' && !Types.isArray( arg ) && !(arg instanceof Number) && arg !== null;
},
getType: function( arg ) {
if ( arg instanceof Number ) {
arg = arg * 1;
}
// handle exceptions that typeof doesn't handle
if ( arg === null ) {
return 'null';
} else if ( Types.isArray( arg ) ) {
return 'array';
} else if ( arg instanceof Date ) {
return 'date';
} else if ( arg instanceof RegExp ) {
return 'regex';
}
var type = typeof arg;
// more resolution on numbers
if ( type === 'number' ) {
if ( isNaN( arg ) ) {
type = 'not-a-number';
} else if ( Infinity === arg ) {
type = 'infinity';
} else if ( Math.ceil( arg ) > Math.floor( arg ) ) {
type = 'float';
} else {
type = 'integer';
}
}
return type;
}
};
'use strict';
var assert = require( 'assert' );
var __ = require( '../' );
describe( 'close', function() {
it( 'should return the correct number of arguments', function() {
var c = __.close( { max: 100 } );
var args = null;
var cb = c( function() {
args = arguments.length;
} );
cb( null, 200 );
assert.strictEqual( args, 2 );
cb( false, 200 );
assert.strictEqual( args, 2 );
cb( undefined, 200 );
assert.strictEqual( args, 2 );
cb( 0, 200 );
assert.strictEqual( args, 2 );
cb( new Error( 'hi' ), 200 );
assert.strictEqual( args, 1 );
cb( new Error( 'hi' ) );
assert.strictEqual( args, 1 );
cb( null );
assert.strictEqual( args, 1 );
cb();
assert.strictEqual( args, 1 );
} );
it( 'should return data once', function() {
var c = __.close();
var calls = 0;
var lastData = null;
var cb = c( function( err, data ) {
lastData = data;
calls++;
} );
cb( null, 200 );
cb( null, 'hi' );
assert.strictEqual( lastData, 200 );
assert.strictEqual( calls, 1 );
} );
it( 'should return data twice', function() {
var c = __.close( {
max: 2
} );
var calls = 0;
var data = [];
var cb = c( function( err, datum ) {
data.push( datum );
calls++;
} );
cb( null, 200 );
cb( null, 'hi' );
cb( null, 'bye' );
assert.deepEqual( data, [ 200, 'hi' ] );
assert.strictEqual( calls, 2 );
} );
it( 'should timeout error', function( done ) {
var c = __.close( {
ttl: 10
} );
var cb = c( function( err, data ) {
try {
assert( err );
assert.strictEqual( data, undefined );
done();
} catch ( e ) {
done( e );
}
} );
setTimeout( function() {
cb( null, true );
}, 100 );
} );
it( 'should throw exception on extra callbacks', function() {
var c = __.close( {
maxException: true
} );
var calls = 0;
var lastData = null;
var cb = c( function( err, data ) {
lastData = data;
calls++;
} );
cb( null, 200 );
assert.throws( function() {
cb( null, 'exception' );
}, /max callbacks 1/ );
assert.strictEqual( calls, 1 );
} );
} );
+20
-257

@@ -1,263 +0,25 @@

"use strict";
'use strict';
var myArray = Array;
var Clone = require( './lib/clone' );
var Close = require( './lib/close' );
var Mixin = require( './lib/mixin' );
var Timer = require( './lib/timer' );
var Types = require( './lib/types' );
if ( !myArray.isArray ) {
myArray = {
isArray: function( arg ) {
return Object.prototype.toString.call( arg ) === '[object Array]';
}
};
}
function isNumber( arg ) {
return typeof arg === 'number' && !isNaN( arg );
}
function isArray( arg ) {
return myArray.isArray( arg );
}
function isObject( arg ) {
return typeof arg === 'object' && !Array.isArray( arg ) && !(arg instanceof Number) && arg !== null;
}
function getType( arg ) {
if ( arg instanceof Number ) {
arg = arg * 1;
}
// handle exceptions that typeof doesn't handle
if ( arg === null ) {
return 'null';
} else if ( isArray( arg ) ) {
return 'array';
} else if ( arg instanceof Date ) {
return 'date';
} else if ( arg instanceof RegExp ) {
return 'regex';
}
var type = typeof arg;
// more resolution on numbers
if ( type === 'number' ) {
if ( isNaN( arg ) ) {
type = 'not-a-number';
} else if ( Infinity === arg ) {
type = 'infinity';
} else if ( Math.ceil( arg ) > Math.floor( arg ) ) {
type = 'float';
} else {
type = 'integer';
}
}
return type;
}
var cloneDepth = 0;
function clone( arg ) {
cloneDepth++;
if ( cloneDepth >= 100 ) {
cloneDepth = 0;
throw new Error( 'max clone depth of 100 reached' );
}
var target = null;
if ( arg instanceof Date ) {
target = new Date( arg.toISOString() );
} else if ( isArray( arg ) ) {
target = [];
for ( var i = 0; i < arg.length; i++ ) {
target[ i ] = clone( arg[ i ] );
}
} else if ( isObject( arg ) ) {
target = {};
for ( var field in arg ) {
if ( arg.hasOwnProperty( field ) ) {
target[ field ] = clone( arg[ field ] );
}
}
} else { // functions, etc. not clonable, and will pass through, though for primitives like strings and numbers, arg is cloning
target = arg;
}
cloneDepth--;
return target;
}
var mixinDepth = 0;
function mixin( arg ) {
mixinDepth++;
if ( mixinDepth >= 100 ) {
mixinDepth = 0;
throw new Error( 'max mixin depth of 100 reached' );
}
var target = clone( arg ); // clone so we don't modify the original
// handle arbitrary number of mixins. precedence is from last to first item passed in.
for ( var i = 1; i < arguments.length; i++ ) {
var source = arguments[ i ];
// mixin the source differently depending on what is in the destination
switch ( getType( target ) ) {
case 'object':
case 'array':
case 'function':
// mixin in the source differently depending on its type
switch ( getType( source ) ) {
case 'array':
case 'object':
case 'function':
// we don't care what descendant of object the source is
for ( var field in source ) {
// don't mixin parent fields
if ( source.hasOwnProperty( field ) ) {
// if the target is an array, only take fields that are integers
if ( Array.isArray( target ) ) {
var fieldFloat = parseFloat( field );
// the field started with a number, or no number at all, then had non-numeric characters
if ( isNaN( fieldFloat ) || fieldFloat.toString().length !== field.length || getType( fieldFloat ) !== 'integer' ) {
continue;
}
}
// recurse mixin differently depending on what the target value is
switch ( getType( target[ field ] ) ) {
// for any non-objects, do this
case 'undefined':
case 'null':
switch ( getType( source[ field ] ) ) {
case 'undefined':
// NO-OP undefined doesn't override anything
break;
case 'null':
target[ field ] = null;
break;
default:
target[ field ] = clone( source[ field ] );
break;
}
break;
// if the target is already an object, we can mixin on it
default:
target[ field ] = mixin( target[ field ], source[ field ] );
break;
}
}
}
break;
default:
// NO-OP, primitives can't mixin to objects, arrays and functions
break;
}
break;
default:
// mixin in the source differently depending on its type
switch ( getType( source ) ) {
// arrays and objects just replace primitives
case 'array':
case 'object':
// override primitives by just passing through a clone of parent
target = clone( source );
break;
default:
// target is a primitive and can't be null or undefined here, and all other primitives have equal precedence, so just pass through
target = source;
break;
}
break;
}
}
mixinDepth--;
return target;
}
function timer() {
// account for overhead within this function, this may not be a good idea
var offset = 1;
var start = new Date().getTime() + offset;
return function( reset ) {
var diff = new Date().getTime() - start;
if ( diff < 0 ) {
diff = 0;
}
if ( reset ) {
start = new Date().getTime() + offset;
}
return diff;
};
}
module.exports = function( obj ) {
return {
clone: function() {
return clone( obj );
return Clone.clone( obj );
},
getType: function() {
return getType( obj );
return Types.getType( obj );
},
isArray: function() {
return isArray( obj );
return Types.isArray( obj );
},
isNumber: function() {
return isNumber( obj );
return Types.isNumber( obj );
},
isObject: function() {
return isObject( obj );
return Types.isObject( obj );
},

@@ -271,3 +33,3 @@ mixin: function() {

}
return mixin.apply( module.exports, args );
return Mixin.mixin.apply( module.exports, args );
}

@@ -277,8 +39,9 @@ };

module.exports.clone = clone;
module.exports.getType = getType;
module.exports.timer = timer;
module.exports.isArray = isArray;
module.exports.isNumber = isNumber;
module.exports.isObject = isObject;
module.exports.mixin = mixin;
module.exports.clone = Clone.clone;
module.exports.close = Close.close;
module.exports.getType = Types.getType;
module.exports.timer = Timer.timer;
module.exports.isArray = Types.isArray;
module.exports.isNumber = Types.isNumber;
module.exports.isObject = Types.isObject;
module.exports.mixin = Mixin.mixin;

@@ -5,3 +5,3 @@ {

"author": "Anthony Hildoer <anthony@bluerival.com>",
"version": "0.2.1",
"version": "0.3.0",
"repository": {

@@ -8,0 +8,0 @@ "type": "git",

@@ -6,2 +6,7 @@ doublescore

close()
Returns a function used to generate callbacks with a service level of max calls and minimum TTL until callback errors
isObject()

@@ -8,0 +13,0 @@

'use strict';
require( './close' );
require( './clone' );

@@ -4,0 +5,0 @@ require( './getType' );