jsprim
Advanced tools
Comparing version 0.4.0 to 0.5.0
@@ -21,2 +21,4 @@ /* | ||
exports.forEachKey = forEachKey; | ||
exports.pluck = pluck; | ||
exports.flattenObject = flattenObject; | ||
exports.validateJsonObject = validateJsonObjectJS; | ||
@@ -31,3 +33,5 @@ exports.validateJsonObjectJS = validateJsonObjectJS; | ||
exports.iso8601 = iso8601; | ||
exports.parseDateTime = parseDateTime; | ||
/* | ||
@@ -120,2 +124,49 @@ * Deep copy an acyclic *basic* Javascript object. This only handles basic | ||
function pluck(obj, key) | ||
{ | ||
mod_assert.equal(typeof (key), 'string'); | ||
return (pluckv(obj, key)); | ||
} | ||
function pluckv(obj, key) | ||
{ | ||
if (obj === null || typeof (obj) !== 'object') | ||
return (undefined); | ||
if (obj.hasOwnProperty(key)) | ||
return (obj[key]); | ||
var i = key.indexOf('.'); | ||
if (i == -1) | ||
return (undefined); | ||
var key1 = key.substr(0, i); | ||
if (!obj.hasOwnProperty(key1)) | ||
return (undefined); | ||
return (pluckv(obj[key1], key.substr(i + 1))); | ||
} | ||
function flattenObject(data, depth) | ||
{ | ||
mod_assert.ok(data !== null); | ||
mod_assert.equal(typeof (data), 'object'); | ||
mod_assert.equal(typeof (depth), 'number'); | ||
mod_assert.ok(depth >= 0); | ||
if (depth === 0) | ||
return ([ data ]); | ||
var rv = []; | ||
var key; | ||
for (key in data) { | ||
flattenObject(data[key], depth - 1).forEach(function (p) { | ||
rv.push([ key ].concat(p)); | ||
}); | ||
} | ||
return (rv); | ||
} | ||
function startsWith(str, prefix) | ||
@@ -143,2 +194,20 @@ { | ||
/* | ||
* Parses a date expressed as a string, as either a number of milliseconds since | ||
* the epoch or any string format that Date accepts, giving preference to the | ||
* former where these two sets overlap (e.g., small numbers). | ||
*/ | ||
function parseDateTime(str) | ||
{ | ||
/* | ||
* This is irritatingly implicit, but significantly more concise than | ||
* alternatives. The "+str" will convert a string containing only a | ||
* number directly to a Number, or NaN for other strings. Thus, if the | ||
* conversion succeeds, we use it (this is the milliseconds-since-epoch | ||
* case). Otherwise, we pass the string directly to the Date | ||
* constructor to parse. | ||
*/ | ||
return (new Date(+str || str)); | ||
} | ||
function validateJsonObjectJSV(schema, input) | ||
@@ -145,0 +214,0 @@ { |
{ | ||
"name": "jsprim", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "utilities for primitive JavaScript types", | ||
@@ -13,5 +13,5 @@ "main": "./lib/jsprim.js", | ||
"dependencies": { | ||
"extsprintf": "1.0.0", | ||
"extsprintf": "1.0.2", | ||
"json-schema": "0.2.2", | ||
"verror": "1.3.3" | ||
"verror": "1.3.6" | ||
}, | ||
@@ -18,0 +18,0 @@ |
@@ -32,2 +32,71 @@ # jsprim: utilities for primitive JavaScript types | ||
### flattenObject(obj, depth) | ||
Flattens an object up to a given level of nesting, returning an array of arrays | ||
of length "depth + 1", where the first "depth" elements correspond to flattened | ||
columns and the last element contains the remaining object . For example: | ||
flattenObject({ | ||
'I': { | ||
'A': { | ||
'i': { | ||
'datum1': [ 1, 2 ], | ||
'datum2': [ 3, 4 ] | ||
}, | ||
'ii': { | ||
'datum1': [ 3, 4 ] | ||
} | ||
}, | ||
'B': { | ||
'i': { | ||
'datum1': [ 5, 6 ] | ||
}, | ||
'ii': { | ||
'datum1': [ 7, 8 ], | ||
'datum2': [ 3, 4 ], | ||
}, | ||
'iii': { | ||
} | ||
} | ||
}, | ||
'II': { | ||
'A': { | ||
'i': { | ||
'datum1': [ 1, 2 ], | ||
'datum2': [ 3, 4 ] | ||
} | ||
} | ||
} | ||
}, 3) | ||
becomes: | ||
[ | ||
[ 'I', 'A', 'i', { 'datum1': [ 1, 2 ], 'datum2': [ 3, 4 ] } ], | ||
[ 'I', 'A', 'ii', { 'datum1': [ 3, 4 ] } ], | ||
[ 'I', 'B', 'i', { 'datum1': [ 5, 6 ] } ], | ||
[ 'I', 'B', 'ii', { 'datum1': [ 7, 8 ], 'datum2': [ 3, 4 ] } ], | ||
[ 'I', 'B', 'iii', {} ], | ||
[ 'II', 'A', 'i', { 'datum1': [ 1, 2 ], 'datum2': [ 3, 4 ] } ] | ||
] | ||
This function is strict: "depth" must be a non-negative integer and "obj" must | ||
be a non-null object with at least "depth" levels of nesting under all keys. | ||
### pluck(obj, key) | ||
Fetch nested property "key" from object "obj", traversing objects as needed. | ||
For example, `pluck(obj, "foo.bar.baz")` is roughly equivalent to | ||
`obj.foo.bar.baz`, except that: | ||
1. If traversal fails, the resulting value is undefined, and no error is | ||
thrown. For example, `pluck({}, "foo.bar")` is just undefined. | ||
2. If "obj" has property "key" directly (without traversing), the | ||
corresponding property is returned. For example, | ||
`pluck({ 'foo.bar': 1 }, 'foo.bar')` is 1, not undefined. This is also | ||
true recursively, so `pluck({ 'a': { 'foo.bar': 1 } }, 'a.foo.bar')` is | ||
also 1, not undefined. | ||
### randElt(array) | ||
@@ -57,2 +126,9 @@ | ||
### parseDateTime(str) | ||
Parses a date expressed as a string, as either a number of milliseconds since | ||
the epoch or any string format that Date accepts, giving preference to the | ||
former where these two sets overlap (e.g., strings containing small numbers). | ||
### validateJsonObject(schema, object) | ||
@@ -63,1 +139,11 @@ | ||
useful Error object. | ||
# Contributing | ||
Code should be "make check" clean. This target assumes that | ||
[jsl](http://github.com/davepacheco/javascriptlint) and | ||
[jsstyle](http://github.com/davepacheco/jsstyle) are on your path. | ||
New tests should generally accompany new functions and bug fixes. The tests | ||
should pass cleanly (run tests/basic.js). |
@@ -120,1 +120,94 @@ /* | ||
jsprim.forEachKey(v, function (_, value) { mod_assert.ok(value > 0); }); | ||
/* flatten */ | ||
v = jsprim.flattenObject({ | ||
'I': { | ||
'A': { | ||
'i': { | ||
'datum1': [ 1, 2 ], | ||
'datum2': [ 3, 4 ] | ||
}, | ||
'ii': { | ||
'datum1': [ 3, 4 ] | ||
} | ||
}, | ||
'B': { | ||
'i': { | ||
'datum1': [ 5, 6 ] | ||
}, | ||
'ii': { | ||
'datum1': [ 7, 8 ], | ||
'datum2': [ 3, 4 ] | ||
}, | ||
'iii': { | ||
} | ||
} | ||
}, | ||
'II': { | ||
'A': { | ||
'i': { | ||
'datum1': [ 1, 2 ], | ||
'datum2': [ 3, 4 ] | ||
} | ||
} | ||
} | ||
}, 3); | ||
mod_assert.deepEqual(v, [ | ||
[ 'I', 'A', 'i', { 'datum1': [ 1, 2 ], 'datum2': [ 3, 4 ] } ], | ||
[ 'I', 'A', 'ii', { 'datum1': [ 3, 4 ] } ], | ||
[ 'I', 'B', 'i', { 'datum1': [ 5, 6 ] } ], | ||
[ 'I', 'B', 'ii', { 'datum1': [ 7, 8 ], 'datum2': [ 3, 4 ] } ], | ||
[ 'I', 'B', 'iii', {} ], | ||
[ 'II', 'A', 'i', { 'datum1': [ 1, 2 ], 'datum2': [ 3, 4 ] } ] | ||
]); | ||
mod_assert.throws(function () { jsprim.flattenObject(null, 3); }); | ||
mod_assert.throws(function () { jsprim.flattenObject('hello', 3); }); | ||
mod_assert.throws(function () { jsprim.flattenObject(3, 3); }); | ||
mod_assert.throws(function () { jsprim.flattenObject({}, 'hello'); }); | ||
mod_assert.throws(function () { jsprim.flattenObject({}, -1); }); | ||
/* pluck */ | ||
mod_assert.equal('hello', jsprim.pluck({ 'world': 'hello' }, 'world')); | ||
mod_assert.equal('hello', jsprim.pluck({ 'world.bar': 'hello' }, 'world.bar')); | ||
mod_assert.equal('hello', jsprim.pluck({ | ||
'world.bar': 'hello', | ||
'world': { | ||
'bar': 'junk' | ||
} | ||
}, 'world.bar')); | ||
mod_assert.equal('junk', jsprim.pluck({ | ||
'world': { | ||
'bar': 'junk' | ||
} | ||
}, 'world.bar')); | ||
mod_assert.ok(undefined === jsprim.pluck({ | ||
'world': { | ||
'bar': 'junk' | ||
} | ||
}, 'world.baz')); | ||
mod_assert.ok(undefined === jsprim.pluck(null, 'junk')); | ||
mod_assert.ok(undefined === jsprim.pluck(undefined, 'junk')); | ||
mod_assert.ok(undefined === jsprim.pluck(3, 'junk')); | ||
mod_assert.ok(undefined === jsprim.pluck('hello', 'junk')); | ||
mod_assert.ok(undefined === jsprim.pluck(true, 'junk')); | ||
mod_assert.ok(undefined === jsprim.pluck({}, '3')); | ||
mod_assert.throws(function () { jsprim.pluck({}, 3); }); | ||
mod_assert.throws(function () { jsprim.pluck({}, {}); }); | ||
mod_assert.throws(function () { jsprim.pluck({}, false); }); | ||
/* parseDateTime */ | ||
mod_assert.equal('2013-04-02T16:12:37.456Z', jsprim.iso8601( | ||
jsprim.parseDateTime('2013-04-02T16:12:37.456Z'))); | ||
mod_assert.equal('2013-04-02T16:12:37.000Z', jsprim.iso8601( | ||
jsprim.parseDateTime('2013-04-02T16:12:37Z'))); | ||
mod_assert.equal('2013-04-02T23:54:41.155Z', jsprim.iso8601( | ||
jsprim.parseDateTime('1364946881155'))); | ||
mod_assert.equal('2013-04-02T23:54:41.155Z', jsprim.iso8601( | ||
jsprim.parseDateTime(1364946881155))); | ||
mod_assert.equal('2013-04-02T23:54:41.000Z', jsprim.iso8601( | ||
jsprim.parseDateTime(new Date(1364946881000).toString()))); | ||
console.log('tests okay'); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
44818
825
147
12
+ Addedextsprintf@1.0.2(transitive)
+ Addedverror@1.3.6(transitive)
- Removedextsprintf@1.0.0(transitive)
- Removedverror@1.3.3(transitive)
Updatedextsprintf@1.0.2
Updatedverror@1.3.6