New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

object-manage

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

object-manage - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

3

gruntfile.js

@@ -0,1 +1,2 @@

'use strict';
module.exports = function(grunt){

@@ -17,3 +18,3 @@

},
src: ['test/init.js','test/*.test.js']
src: ['test/*.test.js']
}

@@ -20,0 +21,0 @@ },

@@ -0,1 +1,2 @@

'use strict';
module.exports = require('./lib/ObjectManage')

@@ -1,3 +0,6 @@

var merge = require('merge-recursive')
, util = require('util')
'use strict';
var util = require('util')
, events = require('events')
, mergeRecursive = require('merge-recursive')
, objectMerge = require('object-merge')

@@ -64,2 +67,3 @@ /**

* @param path
* @returns {boolean}
*/

@@ -69,11 +73,167 @@ var remove = function(target,path){

for(var a,p=path.split('.'),i=0; o&&(a=p[i++]); o=o[a]){
if(i !== p.length && undefined === o[a]) break
else if(i === p.length){
if(i !== p.length && undefined === o[a]){
return false
} else if(i === p.length){
o[a] = undefined
delete o[a]
return true
}
}
return false
}
/**
* Object Manage Validate Instance
* @param verb
* @param message
* @param path
* @param value
* @constructor
*/
var Validate = function(verb,message,path,value){
Error.call(this)
this.message = message
this.verb = verb
this.path = path
this.value = value
}
//inherit Error prototype
util.inherits(Validate,Error)
/**
* Verb to handle the validation call
* @type {null}
*/
Validate.prototype.verb = null
/**
* Path being operated on
* @type {null}
*/
Validate.prototype.path = null
/**
* Value of the call be validated
* @type {undefined}
*/
Validate.prototype.value = undefined
/**
* Validate Helpers construction
* @param path
* @param value
* @constructor
*/
var ValidateHelpers = function(path,value){
this.path = path
this.value = value
}
/**
* Path being operated on
* @type {null}
*/
ValidateHelpers.prototype.path = null
/**
* Value being operated on
* @type {null}
*/
ValidateHelpers.prototype.value = null
/**
* Convenience method to drop a request
* @param message
*/
ValidateHelpers.prototype.drop = function(message){
throw new Validate('drop',message,this.path,this.value)
}
/**
* Convenience method to reject a request
* @param message
*/
ValidateHelpers.prototype.reject = function(message){
throw new Validate('reject',message,this.path,this.value)
}
/**
* Convenience method to warn about a request
* @param message
* @param value
*/
ValidateHelpers.prototype.warn = function(message,value){
throw new Validate('warn',message,this.path,value)
}
/**
* Convenience method to error about a request
* @param message
*/
ValidateHelpers.prototype.error = function(message){
throw new Validate('error',message,this.path,this.value)
}
/**
* Convenience method to succeed a request
* @param value
*/
ValidateHelpers.prototype.ok = function(value){
throw new Validate('ok',null,this.path,value)
}
/**
* Run validation of an action
*
* @param validate Validation function
* @param path Path being evaluated
* @param value Value being evaluated
* @param emit Callback to emit events
* @param pre Callback before emit
* @param post Callback after emit for return
* @returns {*}
*/
var runValidation = function(validate,path,value,emit,pre,post){
var err = null
, self = this
if('string' === typeof emit){
var event = emit
emit = function(verb,message,path,value){
if('ok' === verb || 'warn' === verb){
self.emit(event,path,value)
}
if('ok' !== verb){
self.emit(verb,event,message,path,value)
}
}
}
if(!pre) pre = function(verb,value){return value}
if(!post) post = function(verb,value){return value}
if('function' !== typeof validate){
value = pre('ok',value)
emit('ok','',path,value)
return post('ok',value)
} else {
try {
value = validate.call(new ValidateHelpers(path,value),path,value)
} catch(e){
if(!(e instanceof Validate)){
throw e
} else {
err = e
}
}
if(null === err || 'ok' === err.verb){
if(null !== err && 'ok' === err.verb) value = err.value
value = pre('ok',value)
emit('ok','',path,value)
return post('ok',value)
} else if('warn' === err.verb){
value = pre('warn',value)
emit('warn',err.message,path,value)
return post('warn',value)
} else if('drop' === err.verb){
emit('drop',err.message,path,value)
return post('drop',value)
} else if('reject' === err.verb){
emit('reject',err.message,path,value)
return post('reject',value)
} else {
emit('error',err.message,path,value)
throw new Error(err.message)
}
}
}
/**
* Manage constructor passes the initial argument to ObjectManage.load()

@@ -85,5 +245,7 @@ * and accepts the same set of parameters

var ObjectManage = function(data){
events.EventEmitter.call(this)
this.data = {}
this.load(data)
}
util.inherits(ObjectManage,events.EventEmitter)

@@ -103,2 +265,8 @@ /**

/**
* Reference to the Validate object
* @type {Function}
*/
ObjectManage.prototype.Validate = Validate
/**
* Set respective path to value

@@ -109,6 +277,28 @@ * @param path

ObjectManage.prototype.set = function(path,value){
set(this.data,path,value)
var self = this
return runValidation.call(
self,
self.validateSet,
path,
value,
'set',
function(verb,value){
if('ok' === verb || 'warn' === verb || 'drop' === verb){
set(self.data,path,value)
}
return value
},
function(verb){
return ('ok' === verb || 'warn' === verb || 'drop' === verb)
}
)
}
/**
* Validation for set directives
* @type {null}
*/
ObjectManage.prototype.validateSet = null
/**
* Get value of path returns undefined if path does not exist

@@ -119,6 +309,20 @@ * @param path

ObjectManage.prototype.get = function(path){
return get(this.data,path)
var self = this
return runValidation.call(
self,
self.validateGet,
path,
get(self.data,path),
'get'
)
}
/**
* Validation for get directives
* directly
* @type {null}
*/
ObjectManage.prototype.validateGet = null
/**
* Check if path exists (uses hasOwnProperty and is safe to having undefined set as a value)

@@ -129,15 +333,55 @@ * @param path

ObjectManage.prototype.exists = function(path){
return exists(this.data,path)
var self = this
return runValidation.call(
self,
self.validateExists,
path,
null,
'exists',
function(verb){
if('ok' === verb || 'warn' === verb){
return exists(self.data,path)
} else {
return false
}
}
)
}
/**
* Validation of exists directives
* @type {null}
*/
ObjectManage.prototype.validateExists = null
/**
* Remove value and children at desired path (does this by deleting the value)
* @param path
* @returns {}
* @returns {boolean}
*/
ObjectManage.prototype.remove = function(path){
return remove(this.data,path)
var self = this
return runValidation.call(
self,
self.validateRemove,
path,
null,
'remove',
function(verb,value){
if('ok' === verb || 'warning' === verb){
return remove(self.data,path)
} else {
return value
}
}
)
}
/**
* Validation of removal directives
* @type {null}
*/
ObjectManage.prototype.validateRemove = null
/**
* Merge arguments into data object

@@ -149,15 +393,39 @@ * Can be an Array or recursive Array of objects that get merged

ObjectManage.prototype.load = function(data){
var that = this
var self = this
if(util.isArray(data)){
data.forEach(function(v){
that.load(v)
self.load(v)
})
} else {
if('object' === typeof data){
var depth = this.countDepth(data)
if(depth >= this.maxDepth){
var depth = self.countDepth(data)
if(depth >= self.maxDepth){
self.emit('warning',self.data,'Object being merged is too deep (' + depth +')')
console.log('WARN [object-manage]: Object being merged is too deep (' + depth +')')
console.trace()
}
that.data = merge.recursive(that.data,data) || {}
runValidation.call(
self,
self.validateLoad,
null,
data,
function(verb,message,path,value){
if('ok' === verb){
self.emit('load',value)
} else {
self.emit(verb,'load',message,path,value)
}
},
function(verb,value){
if('ok' === verb || 'warn' === verb){
self.data = self.merge(self.data,value) || {}
return self.data
} else {
return false
}
},
function(verb){
return ('ok' === verb || 'warn' === verb)
}
)
}

@@ -168,2 +436,40 @@ }

/**
* Validation for load directives
* @type {null}
*/
ObjectManage.prototype.validateLoad = null
/**
* Merge implementation using object-merge
* @param obj1
* @param obj2
* @returns {*|exports}
*/
ObjectManage.prototype.objectMerge = function(obj1,obj2){
var opts = objectMerge.createOptions({
depth: this.maxDepth,
throwOnCircularRef: true
})
return objectMerge(opts,obj1,obj2)
}
/**
* Merge implementation using merge-recursive
* @param obj1
* @param obj2
* @returns {*}
*/
ObjectManage.prototype.mergeRecursive = function(obj1,obj2){
return mergeRecursive.recursive(obj1,obj2)
}
/**
* Merge prototype allowed to be overirden
* @param obj1
* @param obj2
* @returns {*|exports}
*/
Object.prototype.merge = ObjectManage.prototype.objectMerge
/**
* Count the depth of an object and return

@@ -170,0 +476,0 @@ * @param object Target object

@@ -6,3 +6,3 @@ {

"bugs": "https://github.com/snailjs/object-manage/issues",
"version": "0.4.0",
"version": "0.5.0",
"author": "Bryan Tong <contact@nullivex.com>",

@@ -14,2 +14,4 @@ "license": "MIT",

"setter",
"exists",
"remove",
"merge",

@@ -28,3 +30,4 @@ "path",

"dependencies": {
"merge-recursive": "~0.0.3"
"object-merge": "~2.5.1",
"merge-recursive": "0.0.3"
},

@@ -31,0 +34,0 @@ "devDependencies": {

@@ -19,22 +19,131 @@ object-manage [![Build Status](https://travis-ci.org/snailjs/object-manage.png?branch=master)](https://travis-ci.org/snailjs/object-manage)

ObjectManage is also an event emitter that allows the internal data object to be watched
and augmented manually.
```js
var ObjectManage = require('object-manage')
, obj = new ObjectManage({box: 'square'})
//construct
var obj = new ObjectManage({box: 'square'})
//watch data
var mydata = {}
obj.on('load',function(data){
mydata = data
})
//load in data
obj.load({foo: 'bar'})
//set a path
obj.set('bas.boo','foo1')
//get a path
obj.get('bas') //{boo: 'foo1'}
obj.get('bas.boo') //'foo1'
//access data directly
console.log(obj.data.bas.boo) //'foo1'
//check if a path exists
obj.exists('bas') //true
obj.exists('badkey') //false
//remove a path
obj.remove('bas')
obj.exists('bas') //false
```
## Inheritance
It is also useful to use ObjectManage as a superconstructor for libraries with options.
Here is a quick example
```js
var ObjectManage = require('object-manage')
, util = require('util')
var myObj = function(data){
ObjectManage.call(this,data)
}
util.inherits(myObj,ObjectManage)
myObj.prototype.foo = function(){
console.log(this.data) //this.data managed by ObjectManage
}
```
## Switching Merge Package
In order to make object-manage more performance friendly in smaller environments
the merger can easily be switched between **object-merge** for **merge-recursive**.
**merge-recursive** will only merge pointers and thus when the object-manage instance
is modified the original objects will be as well. We choose **object-merge** as the
default because it will decouple from the objects being merged in. This comes with a
performance and memory cost.
To use **merge-recursive**
```js
var ObjectManage = require('object-manage')
ObjectManage.prototype.merge = ObjectManage.prototype.mergeRecursive
```
It is also possible to implement one's own merging function.
```js
var ObjectManage = require('object-manage')
ObjectManage.prototype.merge = function(obj1,obj2){
var mergedObject = obj2
return mergedObject
}
```
## Validation
In order for object-manage to be useful in more hostile environments.
It allows for validation functions to be defined per instance.
Quick example of a validation function for setting values
```js
var obj = new ObjectManage()
obj.validateSet = function(path,value){
//your validation code here that calls one of the below functions
//erroneous method that still processes the action
this.warn('should have passed a boolean',value)
//erroneous methods that will halt processing of the action
this.drop('value must be boolean')
this.reject('value must be boolean')
//will throw an exception that must be caught in user space
this.error('something bad happened')
//non erroneous return methods
this.ok(value)
//or
return value
}
```
### Callbacks
The following callbacks are available.
* validateGet `ObjectManage.validateGet` -- Validate get directives
* validateSet `ObjectManage.validateSet` -- Validate set directives
* validateExists `ObjectManage.validateExists` -- Validate exists directives
* validateRemove `ObjectManage.validateRemove` -- Validate remove directives
* validateLoad `ObjectManage.validateLoad` -- Validate load directives
### Verbs
There are 5 verbs used to handle exceptions
* **drop** -- Silently drop the set/get operation (returns undefined for get, set returns true)
* **reject** -- Actively reject the set/get operation and issue an error back to the setter/getter
* **warn** -- Accept the get/set request but still issue an error to the user.
* **error** -- Treated like a regular exception and will be thrown upwards.
* **ok** -- Only accepts the value to returned for processing
## API Reference

@@ -47,2 +156,11 @@

```js
var data = {foo: 'foo'}
var inst = new ObjectManage(data)
```
**NOTE** If watching data via the `load` event is desired data
should not be passed to the construct as it will be impossible to
listen for the `load` event.
### Load Object(s)

@@ -65,3 +183,3 @@

, data3 = {test5: {test6: 'val6'}}
var inst = ObjectManage()
var inst = new ObjectManage()
inst.load([data1,data2,data3])

@@ -119,3 +237,3 @@ ```

inst.exists('mykey.mykey2') //true
inst.remove('mykey')
inst.remove('mykey') //true
inst.exists('mykey.mykey') //false

@@ -134,4 +252,169 @@ ```

## Events
### Set
Fired when a set is processed on the managed object
* path -- Path to be set
* value -- Value to be set to the path
* valid -- If a validation function was used this is the validity of that result (boolean)
```js
var obj = new require('object-manage')()
obj.on('set',function(path,value,valid){
valid = valid ? 'valid' : 'invalid'
console.log('a ' + valid + ' value of (' + value + ') set to (' + path + ')')
})
obj.set('foo','bar')
```
### Get
Fired when a get is processed on the managed object
* path -- Path to be retrieved
* value -- Value of the path retrieved
** valid -- If a validation function was used this is the validity of that result (boolean)
```js
var obj = new require('object-manage')()
obj.on('get',function(path,value){
console.log(value + ' was retrieved from ' + path)
})
obj.get('foo')
```
### Exists
Fired when an exists operation is performed
* path -- Path that is being checked for existance
* exists -- Result of exists check (boolean)
```js
var obj = new require('object-manage')()
obj.on('exists',function(path,exists){
var does = exists ? 'does' : 'does not'
console.log('checked if ' + path + ' exists and it ' + does)
})
obj.exists('foo')
```
### Remove
Fired when an remove operation is performed
* path -- Path that is being checked for existance
* removed -- Result of removal operation (boolean)
```js
var obj = new require('object-manage')()
obj.on('exists',function(path,removed){
var successfully = removed ? 'successfully' : 'unsuccessfully'
console.log(successfully + ' removed path (' + path + ')')
})
obj.remove('foo')
```
### Load
Fired when a load and merge is performed on the managed object
* data -- Result of the load and merge
```js
var obj = new require('object-manage')()
obj.on('load',function(data){
console.log('a merge was performed and the resulting data: ' + data)
})
obj.load({foo: 'bar'})
```
### Drop
Fired when there is a validation `drop`
* verb -- The current action type (get,set)
* message -- The warning message
* path -- Path of the property being operated on
* value -- The value being operated on
```js
var obj = new require('object-manage')()
obj.on('drop',function(verb,message,path,value){
console.log('object-manage drop [' + verb + ':' + path + ']: ' + message)
})
obj.validateSet = function(path,value){
this.drop('not accepting anything')
}
obj.set('foo','will drop') //returns true
```
### Reject
Fired when there is a validation `reject`
* verb -- The current action type (get,set)
* message -- The warning message
* path -- Path of the property being operated on
* value -- The value being operated on
```js
var obj = new require('object-manage')()
obj.on('reject',function(verb,message,path,value){
console.log('object-manage reject [' + verb + ':' + path + ']: ' + message)
})
obj.validateSet = function(path,value){
this.reject('not accepting anything')
}
obj.set('foo','will drop') //returns false
```
### Warning
Fired when there is a set/get/merge warning.
* verb -- The current action type (get,set,merge)
* message -- The warning message
* path -- Path of the property being operated on (blank during merge warnings)
* value -- The value being operated on (the value being merged in during a merge warning)
```js
var obj = new require('object-manage')()
obj.on('warn',function(verb,message,path,value){
console.log('object-manage warning [' + verb + ']: ' + message)
})
obj.load(overlyDeepObject)
```
### Error
Fired when there is a set/get/merge error.
* verb -- The current action type (get,set,merge)
* message -- The warning message
* path -- Path of the property being operated on (blank during merge warnings)
* value -- The value being operated on (the value being merged in during a merge warning)
```js
var obj = new require('object-manage')()
obj.on('error',function(verb,message,path,value){
console.log('object-manage error [' + verb + ']: ' + message)
})
obj.load(overlyDeepObject)
```
## Changelog
### 0.5.0
* ObjectManage is now an event emitter that fires events for watching data see README for event types
* **object-merge** selected as the default merge package.
* Added switchable merger type based on desired environment.
* Added testing against circular referenced objects
* ObjectManage will not modify objects passed into and are decoupled when using **object-merge**
* ObjectManage.merge prototype function added so the merger can be overridden to allow customised usage.
* Validation now supported on get, set, exists, load, and remove.
* Organized tests into groups for easier future additions.
### 0.4.0

@@ -138,0 +421,0 @@ * Added max depth warning for recursive objects that would normally throw `Maximum call stack exceeded`

@@ -0,116 +1,394 @@

'use strict';
var ObjectManage = require('../lib/ObjectManage')
describe.only('ObjectManage',function(){
, expect = require('chai').expect
describe('ObjectManage',function(){
var data1 = {test1: 'val1', test2: 'val2'}
, data2 = {test3: 'val3', test4: 'val4'}
, data3 = {test5: {test6: 'val6'}}
it('should accept data to the constructor',function(){
var obj = new ObjectManage(data1)
expect(obj.data.test1).to.equal('val1')
expect(obj.data.test2).to.equal('val2')
describe('Construction',function(){
it('should accept data to the constructor',function(){
var obj = new ObjectManage(data1)
expect(obj.data.test1).to.equal('val1')
expect(obj.data.test2).to.equal('val2')
})
it('should be able to merge in data after constructing',function(){
var obj = new ObjectManage([data1,data2])
expect(obj.data.test3).to.equal('val3')
expect(obj.data.test4).to.equal('val4')
})
})
it('should be able to merge in data after constructing',function(){
var obj = new ObjectManage([data1,data2])
expect(obj.data.test3).to.equal('val3')
expect(obj.data.test4).to.equal('val4')
describe('Setters and Getters',function(){
it('should be able to get a nested key',function(){
var obj = new ObjectManage([data1,data3])
expect(obj.get('test5.test6')).to.equal('val6')
})
it('should be able to set a nested key',function(){
var obj = new ObjectManage([data1,data3])
obj.set('test5.test7','val7')
expect(obj.data.test5.test7).to.equal('val7')
})
it('should overwrite a key to object if nested below',function(){
var obj = new ObjectManage([data1,data2,data3])
obj.set('test5.test6.new','val8')
expect(obj.data.test5.test6.new).to.equal('val8')
})
it('should returned undefined on a missing key',function(){
var obj = new ObjectManage(data1)
expect(obj.get('test5.test6')).to.equal(undefined)
})
})
it('should be able to get a nested key',function(){
var obj = new ObjectManage([data1,data3])
expect(obj.get('test5.test6')).to.equal('val6')
describe('Removal and Existence',function(){
it('should return true if the property exists',function(){
var obj = new ObjectManage(data1)
expect(obj.exists('test1')).to.equal(true)
})
it('should return false if the property does not exist',function(){
var obj = new ObjectManage()
expect(obj.exists('test1')).to.equal(false)
})
it('should remove a property and all its children',function(){
var obj = new ObjectManage([data1,data2,data3])
obj.remove('test5')
expect(obj.data.hasOwnProperty('test5')).to.equal(false)
})
})
it('should be able to set a nested key',function(){
var obj = new ObjectManage([data1,data3])
obj.set('test5.test7','val7')
expect(obj.data.test5.test7).to.equal('val7')
describe('Merging',function(){
it('should always have an object at .data',function(){
var obj = new ObjectManage()
obj.load(undefined)
expect(obj.data).to.be.an('object')
})
it('should return the whole object if no argument if passed to get',function(){
var obj = new ObjectManage([data1,data2,data3])
expect(Object.keys(obj.get()).length).to.equal(5)
})
it('should merge recursively',function(){
var obj = new ObjectManage(data3)
obj.load({test5: {test7: 'val7'}})
expect(obj.get('test5.test6')).to.equal('val6')
expect(obj.get('test5.test7')).to.equal('val7')
})
})
it('should overwrite a key to object if nested below',function(){
var obj = new ObjectManage([data1,data2,data3])
obj.set('test5.test6.new','val8')
expect(obj.data.test5.test6.new).to.equal('val8')
describe('Events',function(){
it('should be able to watch the data object',function(done){
var obj = new ObjectManage()
obj.once('load',function(data){
expect(data.test5.test6).to.equal('val6')
done()
})
obj.load(data3)
})
it('should emit a set event',function(done){
var obj = new ObjectManage()
obj.once('set',function(path,value){
expect(path).to.equal('foo')
expect(value).to.equal('baz')
done()
})
obj.set('foo','baz')
})
it('should emit a get event',function(done){
var obj = new ObjectManage(data1)
obj.once('get',function(path,value){
expect(path).to.equal('test1')
expect(value).to.equal('val1')
done()
})
obj.get('test1')
})
it('should emit an exists event',function(done){
var obj = new ObjectManage(data1)
obj.once('exists',function(path,exists){
expect(path).to.equal('foo')
expect(exists).to.equal(false)
done()
})
obj.exists('foo')
})
it('should emit a remove event',function(done){
var obj = new ObjectManage(data1)
obj.once('remove',function(path,removed){
expect(path).to.equal('test1')
expect(removed).to.equal(true)
done()
})
obj.remove('test1')
})
it('should emit a load event',function(done){
var obj = new ObjectManage()
obj.once('load',function(data){
expect(data.test1).to.equal('val1')
done()
})
obj.load(data1)
})
})
it('should returned undefined on a missing key',function(){
var obj = new ObjectManage(data1)
expect(obj.get('test5.test6')).to.equal(undefined)
describe('Set with Validation',function(){
it('should validate using drop',function(done){
var obj = new ObjectManage()
obj.validateSet = function(path){
expect(path).to.equal('test1')
this.drop(path + ' must be set to val2')
}
obj.once('drop',function(verb,message,path,value){
expect(verb).to.equal('set')
expect(message).to.equal('test1 must be set to val2')
expect(path).to.equal('test1')
expect(value).to.equal('val3')
done()
})
obj.set('test1','val3')
})
it('should validate using reject',function(done){
var obj = new ObjectManage()
obj.validateSet = function(path){
expect(path).to.equal('test1')
this.reject(path + ' must be set to val2')
}
obj.once('reject',function(verb,message,path,value){
expect(verb).to.equal('set')
expect(message).to.equal('test1 must be set to val2')
expect(path).to.equal('test1')
expect(value).to.equal('val3')
done()
})
obj.set('test1','val3')
})
it('should validate using warn',function(done){
var obj = new ObjectManage()
obj.validateSet = function(path,value){
expect(path).to.equal('test1')
this.warn(path + ' must be set to val2',value)
}
obj.once('warn',function(verb,message,path,value){
expect(verb).to.equal('set')
expect(message).to.equal('test1 must be set to val2')
expect(path).to.equal('test1')
expect(value).to.equal('val3')
expect(obj.get('test1')).to.equal('val3')
done()
})
obj.set('test1','val3')
})
it('should validate using error',function(done){
var obj = new ObjectManage()
obj.validateSet = function(path){
expect(path).to.equal('test1')
this.error(path + ' must be set to val2')
}
obj.once('error',function(verb,message,path,value){
expect(verb).to.equal('set')
expect(message).to.equal('test1 must be set to val2')
expect(path).to.equal('test1')
expect(value).to.equal('val3')
done()
})
expect(function(){obj.set('test1','val3')}).to.throw('test1 must be set to val2')
})
it('should validate using ok',function(done){
var obj = new ObjectManage()
obj.validateSet = function(path,value){
expect(path).to.equal('test1')
this.ok(value)
}
obj.once('set',function(path,value){
expect(path).to.equal('test1')
expect(value).to.equal('val3')
expect(obj.get('test1')).to.equal('val3')
done()
})
obj.set('test1','val3')
})
it('should validate using return',function(done){
var obj = new ObjectManage()
obj.validateSet = function(path,value){
expect(path).to.equal('test1')
return value
}
obj.once('set',function(path,value){
expect(path).to.equal('test1')
expect(value).to.equal('val3')
expect(obj.get('test1')).to.equal('val3')
done()
})
obj.set('test1','val3')
})
})
it('should return true if the property exists',function(){
var obj = new ObjectManage(data1)
expect(obj.exists('test1')).to.equal(true)
describe('Get with Validation',function(){
it('should validate using drop',function(done){
var obj = new ObjectManage()
obj.validateGet = function(path){
expect(path).to.equal('test1')
this.drop(path + ' must be set to val2')
}
obj.once('drop',function(verb,message,path,value){
expect(verb).to.equal('get')
expect(message).to.equal('test1 must be set to val2')
expect(path).to.equal('test1')
expect(value).to.equal('val3')
done()
})
obj.set('test1','val3')
obj.get('test1')
})
it('should validate using reject',function(done){
var obj = new ObjectManage()
obj.validateGet = function(path){
expect(path).to.equal('test1')
this.reject(path + ' must be set to val2')
}
obj.once('reject',function(verb,message,path,value){
expect(verb).to.equal('get')
expect(message).to.equal('test1 must be set to val2')
expect(path).to.equal('test1')
expect(value).to.equal('val3')
done()
})
obj.set('test1','val3')
obj.get('test1')
})
it('should validate using warn',function(done){
var obj = new ObjectManage()
obj.validateGet = function(path,value){
expect(path).to.equal('test1')
this.warn(path + ' must be set to val2',value)
}
obj.once('warn',function(verb,message,path,value){
expect(verb).to.equal('get')
expect(message).to.equal('test1 must be set to val2')
expect(path).to.equal('test1')
expect(value).to.equal('val3')
done()
})
obj.set('test1','val3')
obj.get('test1')
})
it('should validate using error',function(done){
var obj = new ObjectManage()
obj.validateGet = function(path){
expect(path).to.equal('test1')
this.error(path + ' must be set to val2')
}
obj.once('error',function(verb,message,path,value){
expect(verb).to.equal('get')
expect(message).to.equal('test1 must be set to val2')
expect(path).to.equal('test1')
expect(value).to.equal('val3')
done()
})
obj.set('test1','val3')
expect(function(){obj.get('test1')}).to.throw('test1 must be set to val2')
})
it('should validate using ok',function(done){
var obj = new ObjectManage()
obj.validateGet = function(path){
expect(path).to.equal('test1')
this.ok('val4')
}
obj.once('get',function(path,value){
expect(path).to.equal('test1')
expect(value).to.equal('val4')
done()
})
obj.set('test1','val3')
obj.get('test1')
})
it('should validate using return',function(done){
var obj = new ObjectManage()
obj.validateGet = function(path){
expect(path).to.equal('test1')
return 'val4'
}
obj.once('get',function(path,value){
expect(path).to.equal('test1')
expect(value).to.equal('val4')
done()
})
obj.set('test1','val3')
obj.get('test1')
})
})
it('should return false if the property does not exist',function(){
var obj = new ObjectManage()
expect(obj.exists('test1')).to.equal(false)
describe('Circular Reference Handling',function(){
it('should fail on circular referenced objects',function(){
var x = {
'a' : function () {return null}
}
x.b = x.a
var obj = new ObjectManage()
function load(){
obj.load(x)
}
expect(load).to.throw(Error)
})
it('should work using merge-recursive',function(){
var obj = new ObjectManage()
obj.merge = ObjectManage.prototype.mergeRecursive
obj.load(data1)
obj.load(data3)
expect(obj.get('test5.test6')).to.equal('val6')
})
it('should count object depth accurately',function(){
var testObject = {foo: {foo: {foo: 'baz'}}}
, obj = new ObjectManage()
expect(obj.countDepth(testObject)).to.equal(3)
})
it('should warn on objects more than 50 levels deep',function(){
//setup console mocking
var oldLog = console.log
, oldTrace = console.trace
, log = []
, traced = false
console.log = function(msg){
log.push(msg)
}
console.trace = function(){
traced = true
}
var buildObject = function(object,depth,count){
if(undefined === object) object = {}
if(undefined === count) count = 1
if(undefined === depth) depth = 100
if(count > depth) return object
object[count] = buildObject(object[count],depth,(count + 1))
return object
}
//var obj = new ObjectManage()
var badObject = buildObject()
, obj = new ObjectManage()
//verify the limiter on depth is working
expect(obj.countDepth(badObject)).to.equal(obj.maxDepth)
//verify that we can adjust the maxDepth
var oldMaxDepth = obj.maxDepth
obj.maxDepth = 20
expect(obj.countDepth(badObject)).to.equal(20)
//restore original
obj.maxDepth = oldMaxDepth
//load the bad object which should puke
obj.load(badObject)
//verify the warning was thrown
expect(log[0]).to.equal('WARN [object-manage]: Object being merged is too deep (50)')
expect(traced).to.equal(true)
//cleanup
log = []
traced = false
//set the max depth to a lower value and try again
obj.maxDepth = 10
//load the bad object which should puke
obj.load(badObject)
expect(log[0]).to.equal('WARN [object-manage]: Object being merged is too deep (10)')
expect(traced).to.equal(true)
//restore native console functions
console.log = oldLog
console.trace = oldTrace
})
})
it('should remove a property and all its children',function(){
var obj = new ObjectManage([data1,data2,data3])
obj.remove('test5')
expect(obj.data.hasOwnProperty('test5')).to.equal(false)
})
it('should always have an object at .data',function(){
var obj = new ObjectManage()
obj.load(undefined)
expect(obj.data).to.be.an('object')
})
it('should return the whole object if no argument if passed to get',function(){
var obj = new ObjectManage([data1,data2,data3])
expect(Object.keys(obj.get()).length).to.equal(5)
})
it('should merge recursively',function(){
var obj = new ObjectManage(data3)
obj.load({test5: {test7: 'val7'}})
expect(obj.get('test5.test6')).to.equal('val6')
expect(obj.get('test5.test7')).to.equal('val7')
})
it('should count object depth accurately',function(){
var testObject = {foo: {foo: {foo: 'baz'}}}
, obj = new ObjectManage()
expect(obj.countDepth(testObject)).to.equal(3)
})
it('should warn on objects more than 50 levels deep',function(){
//setup console mocking
var oldLog = console.log
, oldTrace = console.trace
, log = []
, traced = false
console.log = function(msg){
log.push(msg)
}
console.trace = function(){
traced = true
}
var buildObject = function(object,depth,count){
if(undefined === object) object = {}
if(undefined === count) count = 1
if(undefined === depth) depth = 100
if(count > depth) return object
object[count] = buildObject(object[count],depth,(count + 1))
return object
}
//var obj = new ObjectManage()
var badObject = buildObject()
, obj = new ObjectManage()
//verify the limiter on depth is working
expect(obj.countDepth(badObject)).to.equal(obj.maxDepth)
//verify that we can adjust the maxDepth
var oldMaxDepth = obj.maxDepth
obj.maxDepth = 20
expect(obj.countDepth(badObject)).to.equal(20)
//restore original
obj.maxDepth = oldMaxDepth
//load the bad object which should puke
obj.load(badObject)
//verify the warning was thrown
expect(log[0]).to.equal('WARN [object-manage]: Object being merged is too deep (50)')
expect(traced).to.equal(true)
//cleanup
log = []
traced = false
//set the max depth to a lower value and try again
obj.maxDepth = 10
//load the bad object which should puke
obj.load(badObject)
expect(log[0]).to.equal('WARN [object-manage]: Object being merged is too deep (10)')
expect(traced).to.equal(true)
//restore native console functions
console.log = oldLog
console.trace = oldTrace
})
})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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