New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

referencejs

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

referencejs - npm Package Compare versions

Comparing version
0.1.1
to
0.1.2
+6
-2
.travis.yml
language: node_js
node_js:
- node
- '7'
- '6'
script:
script:
- npm run lint

@@ -11,1 +11,5 @@ - npm run flow

- npm run build
cache:
directories:
- node_modules
{
"name": "referencejs",
"version": "0.1.1",
"version": "0.1.2",
"description": "Easily create, update, and manipulate references to values in a JSON document.",

@@ -5,0 +5,0 @@ "main": "lib/reference.js",

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

# Referencejs
# Referencejs [![Build Status](https://travis-ci.org/mindblight/referencejs.svg?branch=master)](https://travis-ci.org/mindblight/referencejs)
Reference JS lets you create references to any location in a JSON tree.

@@ -7,1 +8,71 @@ This is useful for

2. For referencing data that doesn't yet exist in the store (e.g. async data)
3. (COMING) For normalizing and denormalizing immutable data
## A Basic Example
import {
createReference,
resolveReference,
dereference,
} from 'referencejs';
const user = {
id: 'abc',
name: 'John Doe'
};
const reference = createReference(['users', user.id]);
let store = {};
store = resolveReference(store, reference, user);
dereference(store, reference) === user;
## dereferencing using `smartDereference`
Dereferencing one reference at a time isn't that useful. `smartDereference` dereferences
every reference in an object. This is useful if you have data structures that differ
significantly from your store
import {
createReference,
smartDereference,
} from 'referencejs';
const store = {
users: {
user1: {
name: 'John Doe'
},
user2: {
name: 'Jane Doe'
},
user3: {
name: 'Billy Doe'
},
user4: {
name: 'Lucy Doe'
}
}
};
const john = createReference(['users', 'user1']);
const jane = createReference(['users', 'user2']);
const billy = createReference(['users', 'user3']);
const lucy = createReference(['users', 'user4']);
const familyTreeReferences = {
father: john,
mother: jane,
children: [billy, lucy]
};
// familyTree will contain the user objects instead of the references
const familyTree = smartDereference(store, familyTree);
## What's a Reference?
A reference is an object that contains everything needed to find a value in a JSON object (called the store).
The signature looks like:
{
path : Array<number|string>
}
// @flow
import isArray from 'lodash/isArray';
import isString from 'lodash/isString';
import isInteger from 'lodash/isInteger';
import isNill from 'lodash/isNil';

@@ -14,3 +15,4 @@ import isPlainObject from 'lodash/isPlainObject';

/* Types */
export type Path = string[];
export type PathSegment = string | number;
export type Path = PathSegment[];
export type Reference = {

@@ -25,4 +27,6 @@ path :Path,

path.length > 0 &&
path.every((pathPart) => {
return isString(pathPart) && pathPart.length > 0;
path.every((pathSegment) => {
// TODO: Add lodash typings and remove 'any' typecast
return (isInteger(pathSegment) && (pathSegment :any) >= 0)
|| isString(pathSegment) && (pathSegment :any).length > 0;
});

@@ -36,5 +40,5 @@ }

/* Reference */
export function createReference(path :Path) {
export function createReference(path :Path) :Reference {
if (!isPath(path)) {
throw Error(`path" must be a non-empty array of strings. Received ${path.join(', ')}`);
throw Error(`path" must be a non-empty array of strings and integers. Received ${path.join(', ')}`);
}

@@ -45,3 +49,3 @@

export function resolveReference(store :Store, reference :Reference, value :*) {
export function resolveReference(store :Store, reference :Reference, value :*) :Store {
if (isNill(store)) {

@@ -48,0 +52,0 @@ throw new Error('"store" must be defined');

@@ -16,317 +16,357 @@ /* eslint-disable prefer-arrow-callback */

describe('isPath', function() {
it('should return false on non-array', function() {
expect(isPath({})).to.be.false;
});
describe('reference', function() {
it('should return false on empty array', function() {
expect(isPath([])).to.be.false;
});
describe('isPath', function() {
it('should return false on non-array', function() {
expect(isPath({})).to.be.false;
});
it('should return false on non-string, non-integer array', function() {
expect(isPath([{}, 'hi'])).to.be.false;
});
it('should return false on empty array', function() {
expect(isPath([])).to.be.false;
});
it('should return false on string array with empty string', function() {
expect(isPath(['', 'hi'])).to.be.false;
});
it('should return false on non-string array', function() {
expect(isPath([1, 'hi'])).to.be.false;
});
it('should return true on string array', function() {
expect(isPath(['bye', 'hi'])).to.be.true;
});
it('should return false on string array with empty string', function() {
expect(isPath(['', 'hi'])).to.be.false;
});
it('should support array indices', function() {
expect(isPath(['array', 5])).to.be.true;
});
});
it('should return true on string array', function() {
expect(isPath(['bye', 'hi'])).to.be.true;
});
describe('isReference', function() {
it('should return false on null', function() {
expect(isReference(null)).to.be.false;
});
it('should return false on object without valid path', function() {
expect(isReference({})).to.be.false;
});
describe('isReference', function() {
it('should return false on null', function() {
expect(isReference(null)).to.be.false;
});
it('should return true on valid reference', function() {
expect(isReference({
path: ['a', 'b'],
})).to.be.true;
});
});
it('should return false on object without valid path', function() {
expect(isReference({})).to.be.false;
});
it('should return true on valid reference', function() {
expect(isReference({
path: ['a', 'b'],
})).to.be.true;
});
describe('createReference', function() {
it('should throw error on null path', function() {
expect(isValueAtReference.bind(null, null)).to.throw(Error);
});
it('should throw error on invalid path', function() {
expect(isValueAtReference.bind(null, [3])).to.throw(Error);
});
describe('createReference', function() {
it('should throw error on null path', function() {
expect(isValueAtReference.bind(null, null)).to.throw(Error);
});
it('should return valid reference', function() {
const path = ['a', 'b'];
const reference = createReference(path);
it('should throw error on invalid path', function() {
expect(isValueAtReference.bind(null, [3])).to.throw(Error);
});
expect(isReference(reference)).to.be.true;
expect(reference).to.have.property('path').equal(path);
});
});
it('should return valid reference', function() {
const path = ['a', 'b'];
const reference = createReference(path);
expect(isReference(reference)).to.be.true;
expect(reference).to.have.property('path').equal(path);
});
describe('resolveReference', function() {
it('should throw error on empty store', function() {
expect(resolveReference.bind(null, null)).to.throw(Error);
});
it('should throw error on invalid reference', function() {
expect(resolveReference.bind(null, {}, {})).to.throw(Error);
});
describe('resolveReference', function() {
it('should throw error on empty store', function() {
expect(resolveReference.bind(null, null)).to.throw(Error);
});
it('should not mutate the passed state', function() {
const reference = createReference(['a', 'b']);
const state = {
a: 1,
b: 'hi',
};
it('should throw error on invalid reference', function() {
expect(resolveReference.bind(null, {}, {})).to.throw(Error);
});
const expectedState = cloneDeep(state);
it('should not mutate the passed state', function() {
const reference = createReference(['a', 'b']);
const state = {
a: 1,
b: 'hi',
};
resolveReference(state, reference, 5);
const expectedState = cloneDeep(state);
expect(state).to.deep.equal(expectedState);
});
resolveReference(state, reference, 5);
it('should return state with value placed at reference.path', function() {
const path = ['a', 'b'];
const reference = createReference(path);
const value = 5;
const initialState = {
c: 6,
};
const state = resolveReference(initialState, reference, value);
expect(state).to.deep.equal(expectedState);
});
expect(state).to.have.property('c').equal(6);
expect(state).to.have.deep.property(path.join('.')).equal(value);
});
it('should return state with value placed at reference.path', function() {
const path = ['a', 'b'];
const reference = createReference(path);
const value = 5;
const initialState = {
c: 6,
};
const state = resolveReference(initialState, reference, value);
it('should handle arrays in store', function() {
const path = ['a', 0];
const reference = createReference(path);
const value = 'foo';
const initialState = {
a: [],
};
const state = resolveReference(initialState, reference, value);
const expectedState = {
a: [value],
};
expect(state).to.have.property('c').equal(6);
expect(state).to.have.deep.property(path.join('.')).equal(value);
});
expect(state).to.deep.equal(expectedState);
});
it('should handle deep object creation', function() {
const path = ['a', 0, 'b'];
const reference = createReference(path);
const value = 'foo';
const initialState = {};
const state = resolveReference(initialState, reference, value);
const expectedState = {
a: [{
b: value,
}],
};
describe('isValueAtReference', function() {
it('should throw error on empty store', function() {
expect(dereference.bind(null, null)).to.throw(Error);
});
expect(state).to.deep.equal(expectedState);
});
});
it('should throw error on invalid reference', function() {
expect(dereference.bind(null, {}, {})).to.throw(Error);
});
it('should return false when reference does not exist', function() {
const reference = createReference(['a']);
expect(isValueAtReference({}, reference)).to.be.false;
});
describe('isValueAtReference', function() {
it('should throw error on empty store', function() {
expect(dereference.bind(null, null)).to.throw(Error);
});
it('should return value at reference', function() {
const value = 9;
const store = {
a: {
b: value,
},
};
const reference = createReference(['a', 'b']);
it('should throw error on invalid reference', function() {
expect(dereference.bind(null, {}, {})).to.throw(Error);
});
expect(isValueAtReference(store, reference)).to.be.true;
});
it('should return false when reference does not exist', function() {
const reference = createReference(['a']);
expect(isValueAtReference({}, reference)).to.be.false;
});
it('should return value at reference', function() {
const value = 9;
const store = {
a: {
b: value,
},
};
const reference = createReference(['a', 'b']);
describe('dereference', function() {
it('should throw error on empty store', function() {
expect(dereference.bind(null, null)).to.throw(Error);
});
expect(isValueAtReference(store, reference)).to.be.true;
});
});
it('should throw error on invalid reference', function() {
expect(dereference.bind(null, {}, {})).to.throw(Error);
});
it('should return EMPTY_REFERENCE when reference does not exist', function() {
expect(dereference({}, createReference(['a']))).to.equal(EMPTY_REFERENCE);
});
describe('dereference', function() {
it('should throw error on empty store', function() {
expect(dereference.bind(null, null)).to.throw(Error);
});
it('should return value at reference', function() {
const value = 9;
const store = {
a: {
b: value,
},
};
const reference = createReference(['a', 'b']);
it('should throw error on invalid reference', function() {
expect(dereference.bind(null, {}, {})).to.throw(Error);
});
expect(dereference(store, reference)).to.equal(value);
});
it('should return EMPTY_REFERENCE when reference does not exist', function() {
expect(dereference({}, createReference(['a']))).to.equal(EMPTY_REFERENCE);
});
it('should return value at reference', function() {
const value = 9;
const store = {
a: {
b: value,
},
};
const reference = createReference(['a', 'b']);
describe('smartDereference', function() {
const value1 = 9;
const value2 = 20;
let store;
let reference1;
let reference2;
expect(dereference(store, reference)).to.equal(value);
});
beforeEach(function() {
store = {
a: {
b: value1,
c: value2,
},
};
reference1 = createReference(['a', 'b']);
reference2 = createReference(['a', 'c']);
});
it('should derefence arrays', function() {
const value = {};
const store = {
a: [value],
};
const reference = createReference(['a', 0]);
it('should throw error on null store', function() {
expect(smartDereference.bind(null, null)).to.throw(Error);
});
expect(dereference(store, reference)).to.equal(value);
});
});
it('should return EMPTY_REFERENCE when reference does not exist', function() {
expect(smartDereference({}, createReference(['a']))).to.equal(EMPTY_REFERENCE);
});
it('should return value for non-reference input', function() {
const value = Symbol();
expect(smartDereference(store, value)).to.equal(value);
});
describe('smartDereference', function() {
const value1 = 9;
const value2 = 20;
let store;
let reference1;
let reference2;
it('should return value at reference', function() {
expect(smartDereference(store, reference1)).to.equal(value1);
});
beforeEach(function() {
store = {
a: {
b: value1,
c: value2,
},
};
reference1 = createReference(['a', 'b']);
reference2 = createReference(['a', 'c']);
});
it('should return reference in array', function() {
const input = [reference1, reference2];
const expected = [value1, value2];
it('should throw error on null store', function() {
expect(smartDereference.bind(null, null)).to.throw(Error);
});
expect(smartDereference(store, input)).to.deep.equal(expected);
});
it('should return EMPTY_REFERENCE when reference does not exist', function() {
expect(smartDereference({}, createReference(['a']))).to.equal(EMPTY_REFERENCE);
});
it('should ignore non-reference in array', function() {
const input = [reference1, value2];
const expected = [value1, value2];
it('should return value for non-reference input', function() {
const value = Symbol();
expect(smartDereference(store, value)).to.equal(value);
});
expect(smartDereference(store, input)).to.deep.equal(expected);
});
it('should return value at reference', function() {
expect(smartDereference(store, reference1)).to.equal(value1);
});
it('should deeply handle arrays', function() {
const input = [reference1, [reference2]];
const expected = [value1, [value2]];
it('should return reference in array', function() {
const input = [reference1, reference2];
const expected = [value1, value2];
expect(smartDereference(store, input)).to.deep.equal(expected);
});
expect(smartDereference(store, input)).to.deep.equal(expected);
});
it('should handle plain objects', function() {
const input = {
foo: reference1,
bar: reference2,
};
const expected = {
foo: value1,
bar: value2,
};
it('should ignore non-reference in array', function() {
const input = [reference1, value2];
const expected = [value1, value2];
expect(smartDereference(store, input)).to.deep.equal(expected);
});
expect(smartDereference(store, input)).to.deep.equal(expected);
});
it('should deep handle plain objects', function() {
const input = {
foo: reference1,
bar: {
baz: reference2,
},
};
const expected = {
foo: value1,
bar: {
baz: value2,
},
};
it('should deeply handle arrays', function() {
const input = [reference1, [reference2]];
const expected = [value1, [value2]];
expect(smartDereference(store, input)).to.deep.equal(expected);
});
expect(smartDereference(store, input)).to.deep.equal(expected);
});
it('should not recurse by default', function() {
reference1 = createReference(['a']);
reference2 = createReference(['c']);
const object = {
b: reference2,
};
store = {
a: object,
c: value2,
};
it('should handle plain objects', function() {
const input = {
foo: reference1,
bar: reference2,
};
const expected = {
foo: value1,
bar: value2,
};
const input = {
foo: reference1,
};
const expected = {
foo: object,
};
expect(smartDereference(store, input)).to.deep.equal(expected);
});
expect(smartDereference(store, input)).to.deep.equal(expected);
});
it('should deep handle plain objects', function() {
const input = {
foo: reference1,
bar: {
baz: reference2,
},
};
const expected = {
foo: value1,
bar: {
baz: value2,
},
};
it('should dereference itself', function() {
reference1 = createReference(['b', 'b1']);
reference2 = createReference(['c']);
store = {
a: reference1,
b: {
b1: value1,
},
c: value2,
d: {
d1: reference2,
},
e: reference1,
};
expect(smartDereference(store, input)).to.deep.equal(expected);
});
const expected = {
a: value1,
b: {
b1: value1,
},
c: value2,
d: {
d1: value2,
},
e: value1,
};
it('should not recurse by default', function() {
reference1 = createReference(['a']);
reference2 = createReference(['c']);
const object = {
b: reference2,
};
store = {
a: object,
c: value2,
};
expect(smartDereference(store, store)).to.deep.equal(expected);
});
const input = {
foo: reference1,
};
const expected = {
foo: object,
};
it.skip('should not recurse when recurse=true', function() {
reference1 = createReference(['a']);
reference2 = createReference(['c']);
const object = {
b: reference2,
};
store = {
a: object,
c: value2,
};
expect(smartDereference(store, input)).to.deep.equal(expected);
});
const input = {
foo: reference1,
};
const expected = {
foo: {
b: value2,
},
};
it('should dereference itself', function() {
reference1 = createReference(['b', 'b1']);
reference2 = createReference(['c']);
store = {
a: reference1,
b: {
b1: value1,
},
c: value2,
d: {
d1: reference2,
},
e: reference1,
};
expect(smartDereference(store, input, true)).to.deep.equal(expected);
});
const expected = {
a: value1,
b: {
b1: value1,
},
c: value2,
d: {
d1: value2,
},
e: value1,
};
expect(smartDereference(store, store)).to.deep.equal(expected);
});
it.skip('should not recurse when recurse=true', function() {
reference1 = createReference(['a']);
reference2 = createReference(['c']);
const object = {
b: reference2,
};
store = {
a: object,
c: value2,
};
const input = {
foo: reference1,
};
const expected = {
foo: {
b: value2,
},
};
expect(smartDereference(store, input, true)).to.deep.equal(expected);
});
});