(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 10 years ago
parent cdeea1fb4d
commit 4da8a2b0a2

@ -19,6 +19,8 @@ Docuris have many advantages:
Give Docuris a try! Give Docuris a try!
## Usage ## Usage
### `parse(string)`
Parse id string: Parse id string:
```js ```js
var docuri = require('docuri'); var docuri = require('docuri');
@ -32,6 +34,7 @@ docuri.parse('mytype/myid/mysubtype/myindex/myversion');
// } // }
``` ```
### `stringify(object)`
Build id string from object: Build id string from object:
```js ```js
docuri.stringify({ docuri.stringify({
@ -44,6 +47,7 @@ docuri.stringify({
// 'mytype/myid/mysubtype/myindex/myversion' // 'mytype/myid/mysubtype/myindex/myversion'
``` ```
### `merge(objectOrString)`
Change id string components: Change id string components:
```js ```js
docuri.merge('mytype/myid/mysubtype/myindex/myversion', { 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' // '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: Use custom definition:
```js ```js
docuri(); docuri();
@ -65,6 +88,8 @@ docuri.parse('42/answer');
// meta: 'answer' // meta: 'answer'
// } // }
``` ```
Note: `definition` MUST be an array of strings with at least one item.
## Browser support ## Browser support
To use docid in your client-side application, browserify it like this: To use docid in your client-side application, browserify it like this:

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

@ -1,6 +1,6 @@
{ {
"name": "docuri", "name": "docuri",
"version": "2.1.0", "version": "2.2.0",
"description": "Rich document ids for CouchDB", "description": "Rich document ids for CouchDB",
"main": "index.js", "main": "index.js",
"scripts": { "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 test = require('tap').test;
var docuri = require('..'); var parts = require('..').parts;
test('default configuration', function(t) { test('parts of type string', function(t) {
t.deepEqual(docuri(), ['type', 'id', 'subtype', 'index', 'version'], 'should return default parts'); t.deepEqual(parts('type'), ['type'], 'should return array including type');
t.end(); t.end();
}); });
test('parts of type/id string', function(t) {
test('set configuration', function(t) { t.deepEqual(parts('type/id'), ['type', 'id'], 'should return array including type and id');
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(); t.end();
}); });
test('parts of type/id/subtype string', function(t) {
test('change configuration', function(t) { t.deepEqual(parts('type/id/subtype'), ['type', 'id', 'subtype'], 'should return array including type, id and subtype');
var parts = ['my', 'parts']; t.end();
docuri(parts); });
t.deepEqual(docuri(), parts, 'should return custom parts'); 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(); t.end();
}); });
test('use changed configuration', function(t) { test('parts of type object', function(t) {
var parts = ['my', 'parts']; t.deepEqual(parts({ type: 'type' }), ['type'], 'should return array including type');
t.deepEqual(docuri(parts).parse('one/two'), { my: 'one', parts: 'two'}, 'should use custom parts'); 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(); t.end();
}); });

Loading…
Cancel
Save