(closes #7) - implements arity and parts

`docuri.parts` array of components, without trailing `undefined` components
`docuri.arity` length of parts.
pull/9/head
Johannes J. Schmidt 11 years ago
parent cdeea1fb4d
commit 4da8a2b0a2

@ -19,6 +19,8 @@ Docuris have many advantages:
Give Docuris a try!
## Usage
### `parse(string)`
Parse id string:
```js
var docuri = require('docuri');
@ -32,6 +34,7 @@ docuri.parse('mytype/myid/mysubtype/myindex/myversion');
// }
```
### `stringify(object)`
Build id string from object:
```js
docuri.stringify({
@ -44,6 +47,7 @@ docuri.stringify({
// 'mytype/myid/mysubtype/myindex/myversion'
```
### `merge(objectOrString)`
Change id string components:
```js
docuri.merge('mytype/myid/mysubtype/myindex/myversion', {
@ -52,6 +56,25 @@ docuri.merge('mytype/myid/mysubtype/myindex/myversion', {
// 'my_new_type/myid/mysubtype/myindex/myversion'
```
### `parts(objectOrString)`
Array of components. Trailing `undefined` components are stripped off:
```js
docuri.parts('mytype/myid/');
// ['mytype', 'myid']
docuri.parts({ type: 'mytype', subtype: 'mysubtype' });
// ['mytype', undefined, 'mysubtype']
```
### `arity(objectOrString)`
Length of parts:
```js
docuri.arity('mytype/myid/');
// 2
docuri.arity({ type: 'mytype', subtype: 'mysubtype' });
// 3
```
### `docuri([definition])`
Use custom definition:
```js
docuri();
@ -65,6 +88,8 @@ docuri.parse('42/answer');
// meta: 'answer'
// }
```
Note: `definition` MUST be an array of strings with at least one item.
## Browser support
To use docid in your client-side application, browserify it like this:

@ -6,25 +6,41 @@
*/
// type/id/subtype/index/version
var PARTS = ['type', 'id', 'subtype', 'index', 'version'];
var DEFINITION = ['type', 'id', 'subtype', 'index', 'version'];
function docuri(parts) {
if (parts) {
PARTS = parts;
function docuri(definition) {
if (definition) {
DEFINITION = definition;
return docuri;
}
return PARTS;
return DEFINITION;
}
docuri.parts = function(obj) {
if (typeof obj === 'string') {
obj = docuri.parse(obj);
}
var parts = DEFINITION.map(function(part) {
return obj[part];
});
while (parts.length && typeof parts[parts.length - 1] === 'undefined') {
parts.pop();
}
return parts;
};
docuri.parse = function(str) {
str = str || '';
return str.split('/').reduce(function(obj, value, i) {
if (value) {
obj[PARTS[i]] = value;
obj[DEFINITION[i]] = value;
}
return obj;
@ -34,17 +50,17 @@ docuri.parse = function(str) {
docuri.stringify = function(obj) {
obj = obj || {};
return PARTS.map(function(part) {
return typeof obj[part] === 'undefined' ? '' : obj[part];
}).join('/').replace(/\/+$/, '');
return docuri.parts(obj).join('/');
};
docuri.merge = function(str, objToMerge) {
docuri.merge = function(obj, objToMerge) {
objToMerge = objToMerge || {};
var obj = docuri.parse(str);
if (typeof obj === 'string') {
obj = docuri.parse(obj);
}
PARTS.forEach(function(part) {
DEFINITION.forEach(function(part) {
if (objToMerge[part]) {
obj[part] = objToMerge[part];
}
@ -53,6 +69,14 @@ docuri.merge = function(str, objToMerge) {
return docuri.stringify(obj);
};
docuri.arity = function(obj) {
if (typeof obj === 'string') {
obj = docuri.parse(obj);
}
return docuri.parts(obj).length;
};
module.exports = docuri;

@ -1,6 +1,6 @@
{
"name": "docuri",
"version": "2.1.0",
"version": "2.2.0",
"description": "Rich document ids for CouchDB",
"main": "index.js",
"scripts": {

@ -0,0 +1,36 @@
var test = require('tap').test;
var arity = require('..').arity;
test('arity of type string', function(t) {
t.equal(arity('type'), 1, 'should return 1');
t.end();
});
test('arity of type/id string', function(t) {
t.equal(arity('type/id'), 2, 'should return 2');
t.end();
});
test('arity of type/id/subtype string', function(t) {
t.equal(arity('type/id/subtype'), 3, 'should return 3');
t.end();
});
test('arity of type//subtype string', function(t) {
t.equal(arity('type//subtype'), 3, 'should return 3');
t.end();
});
test('arity of type object', function(t) {
t.equal(arity({ type: 'type' }), 1, 'should return 1');
t.end();
});
test('arity of type/id object', function(t) {
t.equal(arity({ type: 'type', id: 'id'}), 2, 'should return 2');
t.end();
});
test('arity of type/id/subtype object', function(t) {
t.equal(arity({ type: 'type', id: 'id', subtype: 'subtype' }), 3, 'should return 3');
t.end();
});
test('arity of type//subtype object', function(t) {
t.equal(arity({ type: 'type', subtype: 'subtype' }), 3, 'should return 3');
t.end();
});

@ -0,0 +1,28 @@
var test = require('tap').test;
var docuri = require('..');
test('default configuration', function(t) {
t.deepEqual(docuri(), ['type', 'id', 'subtype', 'index', 'version'], 'should return default parts');
t.end();
});
test('set configuration', function(t) {
var parts = ['my', 'parts'];
t.type(docuri(parts).merge, 'function', 'should return docuri api: merge');
t.type(docuri(parts).parse, 'function', 'should return docuri api: parse');
t.type(docuri(parts).stringify, 'function', 'should return docuri api: stringify');
t.end();
});
test('change configuration', function(t) {
var parts = ['my', 'parts'];
docuri(parts);
t.deepEqual(docuri(), parts, 'should return custom parts');
t.end();
});
test('use changed configuration', function(t) {
var parts = ['my', 'parts'];
t.deepEqual(docuri(parts).parse('one/two'), { my: 'one', parts: 'two'}, 'should use custom parts');
t.end();
});

@ -38,3 +38,14 @@ test('missing second argument', function(t) {
});
test('changing type component using object', function(t) {
t.equal(merge({
type: 'type',
id: 'id',
subtype: 'subtype',
index: 'index',
version: 'version'
}, {type:'new_type'}), 'new_type/id/subtype/index/version', 'should return docuri string with type changed');
t.end();
});

@ -1,28 +1,36 @@
var test = require('tap').test;
var docuri = require('..');
var parts = require('..').parts;
test('default configuration', function(t) {
t.deepEqual(docuri(), ['type', 'id', 'subtype', 'index', 'version'], 'should return default parts');
test('parts of type string', function(t) {
t.deepEqual(parts('type'), ['type'], 'should return array including type');
t.end();
});
test('set configuration', function(t) {
var parts = ['my', 'parts'];
t.type(docuri(parts).merge, 'function', 'should return docuri api: merge');
t.type(docuri(parts).parse, 'function', 'should return docuri api: parse');
t.type(docuri(parts).stringify, 'function', 'should return docuri api: stringify');
test('parts of type/id string', function(t) {
t.deepEqual(parts('type/id'), ['type', 'id'], 'should return array including type and id');
t.end();
});
test('change configuration', function(t) {
var parts = ['my', 'parts'];
docuri(parts);
t.deepEqual(docuri(), parts, 'should return custom parts');
test('parts of type/id/subtype string', function(t) {
t.deepEqual(parts('type/id/subtype'), ['type', 'id', 'subtype'], 'should return array including type, id and subtype');
t.end();
});
test('parts of type//subtype string', function(t) {
t.deepEqual(parts('type//subtype'), ['type', undefined, 'subtype'], 'should return array including type, undefined and subtype');
t.end();
});
test('use changed configuration', function(t) {
var parts = ['my', 'parts'];
t.deepEqual(docuri(parts).parse('one/two'), { my: 'one', parts: 'two'}, 'should use custom parts');
test('parts of type object', function(t) {
t.deepEqual(parts({ type: 'type' }), ['type'], 'should return array including type');
t.end();
});
test('parts of type/id object', function(t) {
t.deepEqual(parts({ type: 'type', id: 'id'}), ['type', 'id'], 'should return array including type and id');
t.end();
});
test('parts of type/id/subtype object', function(t) {
t.deepEqual(parts({ type: 'type', id: 'id', subtype: 'subtype' }), ['type', 'id', 'subtype'], 'should return array including type, id and subtype');
t.end();
});
test('parts of type//subtype object', function(t) {
t.deepEqual(parts({ type: 'type', subtype: 'subtype' }), ['type', undefined, 'subtype'], 'should return array including type, undefined and subtype');
t.end();
});

Loading…
Cancel
Save