Comparing version 1.0.3 to 1.1.0
@@ -29,2 +29,3 @@ // Load modules | ||
var group = options.group || '?'; | ||
var sort = options.sort || 0; // Used for merging only | ||
@@ -40,2 +41,3 @@ Hoek.assert(before.indexOf(group) === -1, 'Item cannot come before itself:', group); | ||
seq: self._items.length, | ||
sort: sort, | ||
before: before, | ||
@@ -59,2 +61,35 @@ after: after, | ||
internals.Topo.prototype.merge = function (others) { | ||
others = [].concat(others); | ||
for (var o = 0, ol = others.length; o < ol; ++o) { | ||
var other = others[o]; | ||
if (other) { | ||
for (var i = 0, il = other._items.length; i < il; ++i) { | ||
var item = Hoek.shallow(other._items[i]); | ||
this._items.push(item); | ||
} | ||
} | ||
} | ||
// Sort items | ||
this._items.sort(internals.mergeSort); | ||
for (i = 0, il = this._items.length; i < il; ++i) { | ||
this._items[i].seq = i; | ||
} | ||
var error = this._sort(); | ||
Hoek.assert(!error, 'merge created a dependencies error'); | ||
return this.nodes; | ||
}; | ||
internals.mergeSort = function (a, b) { | ||
return a.sort === b.sort ? 0 : (a.sort < b.sort ? -1 : 1); | ||
}; | ||
internals.Topo.prototype._sort = function () { | ||
@@ -61,0 +96,0 @@ |
{ | ||
"name": "topo", | ||
"description": "Topological sorting with grouping support", | ||
"version": "1.0.3", | ||
"version": "1.1.0", | ||
"repository": "git://github.com/hapijs/topo", | ||
@@ -14,3 +14,3 @@ "main": "lib/index.js", | ||
"engines": { | ||
"node": ">=0.10.32" | ||
"node": ">=0.10.40" | ||
}, | ||
@@ -21,3 +21,3 @@ "dependencies": { | ||
"devDependencies": { | ||
"lab": "5.x.x", | ||
"lab": "6.x.x", | ||
"code": "1.x.x" | ||
@@ -24,0 +24,0 @@ }, |
@@ -10,10 +10,14 @@ # topo | ||
## Usage | ||
See the [API Reference](API.md) | ||
**Example** | ||
```node | ||
var Topo = require('topo'); | ||
var topo = new Topo(); | ||
var morning = new Topo(); | ||
topo.add('Nap', { after: ['breakfast', 'prep'] }); | ||
morning.add('Nap', { after: ['breakfast', 'prep'] }); | ||
topo.add([ | ||
morning.add([ | ||
'Make toast', | ||
@@ -23,24 +27,5 @@ 'Pour juice' | ||
topo.add('Eat breakfast', { group: 'breakfast' }); | ||
morning.add('Eat breakfast', { group: 'breakfast' }); | ||
topo.nodes; // ['Make toast', 'Pour juice', 'Eat breakfast', 'Nap'] | ||
morning.nodes; // ['Make toast', 'Pour juice', 'Eat breakfast', 'Nap'] | ||
``` | ||
### `Topo` | ||
The `Topo` object is the container for topologically sorting a list of nodes with non-circular interdependencies. | ||
#### `new Topo()` | ||
Creates a new `Topo` object. | ||
#### `topo.add(nodes, [options])` | ||
Specifies an additional node or list of nodes to be topologically sorted where: | ||
- `nodes` - a mixed value or array of mixed values to be added as nodes to the topologically sorted list. | ||
- `options` - optional sorting information about the `nodes`: | ||
- `group` - a string naming the group to which `nodes` should be assigned. The group name `'?'` is reserved. | ||
- `before` - a string or array of strings specifying the groups that `nodes` must precede in the topological sort. | ||
- `after` - a string or array of strings specifying the groups that `nodes` must succeed in the topological sort. | ||
Returns an array of the topologically sorted nodes. | ||
#### `topo.nodes` | ||
An array of the topologically sorted nodes. This list is renewed upon each call to [`topo.add()`](#topoaddnodes-options). |
@@ -153,2 +153,115 @@ // Load modules | ||
}); | ||
describe('merge()', function () { | ||
it('merges objects', function (done) { | ||
var topo = new Topo(); | ||
topo.add('0', { before: 'a' }); | ||
topo.add('2', { before: 'a' }); | ||
topo.add('4', { after: 'c', group: 'b' }); | ||
topo.add('6', { group: 'd' }); | ||
topo.add('8', { before: 'd' }); | ||
expect(topo.nodes.join('')).to.equal('02486'); | ||
var other = new Topo(); | ||
other.add('1', { after: 'f', group: 'a' }); | ||
other.add('3', { before: ['b', 'c'], group: 'a' }); | ||
other.add('5', { group: 'c' }); | ||
other.add('7', { group: 'e' }); | ||
other.add('9', { after: 'c', group: 'a' }); | ||
expect(other.nodes.join('')).to.equal('13579'); | ||
topo.merge(other); | ||
expect(topo.nodes.join('')).to.equal('0286135479'); | ||
done(); | ||
}); | ||
it('merges objects (explicit sort)', function (done) { | ||
var topo = new Topo(); | ||
topo.add('0', { before: 'a', sort: 1 }); | ||
topo.add('2', { before: 'a', sort: 2 }); | ||
topo.add('4', { after: 'c', group: 'b', sort: 3 }); | ||
topo.add('6', { group: 'd', sort: 4 }); | ||
topo.add('8', { before: 'd', sort: 5 }); | ||
expect(topo.nodes.join('')).to.equal('02486'); | ||
var other = new Topo(); | ||
other.add('1', { after: 'f', group: 'a', sort: 6 }); | ||
other.add('3', { before: ['b', 'c'], group: 'a', sort: 7 }); | ||
other.add('5', { group: 'c', sort: 8 }); | ||
other.add('7', { group: 'e', sort: 9 }); | ||
other.add('9', { after: 'c', group: 'a', sort: 10 }); | ||
expect(other.nodes.join('')).to.equal('13579'); | ||
topo.merge(other); | ||
expect(topo.nodes.join('')).to.equal('0286135479'); | ||
done(); | ||
}); | ||
it('merges objects (mixed sort)', function (done) { | ||
var topo = new Topo(); | ||
topo.add('0', { before: 'a', sort: 1 }); | ||
topo.add('2', { before: 'a', sort: 3 }); | ||
topo.add('4', { after: 'c', group: 'b', sort: 5 }); | ||
topo.add('6', { group: 'd', sort: 7 }); | ||
topo.add('8', { before: 'd', sort: 9 }); | ||
expect(topo.nodes.join('')).to.equal('02486'); | ||
var other = new Topo(); | ||
other.add('1', { after: 'f', group: 'a', sort: 2 }); | ||
other.add('3', { before: ['b', 'c'], group: 'a', sort: 4 }); | ||
other.add('5', { group: 'c', sort: 6 }); | ||
other.add('7', { group: 'e', sort: 8 }); | ||
other.add('9', { after: 'c', group: 'a', sort: 10 }); | ||
expect(other.nodes.join('')).to.equal('13579'); | ||
topo.merge(other); | ||
expect(topo.nodes.join('')).to.equal('0213547869'); | ||
done(); | ||
}); | ||
it('merges objects (multiple)', function (done) { | ||
var topo1 = new Topo(); | ||
topo1.add('0', { before: 'a', sort: 1 }); | ||
topo1.add('2', { before: 'a', sort: 3 }); | ||
topo1.add('4', { after: 'c', group: 'b', sort: 5 }); | ||
var topo2 = new Topo(); | ||
topo2.add('6', { group: 'd', sort: 7 }); | ||
topo2.add('8', { before: 'd', sort: 9 }); | ||
var other = new Topo(); | ||
other.add('1', { after: 'f', group: 'a', sort: 2 }); | ||
other.add('3', { before: ['b', 'c'], group: 'a', sort: 4 }); | ||
other.add('5', { group: 'c', sort: 6 }); | ||
other.add('7', { group: 'e', sort: 8 }); | ||
other.add('9', { after: 'c', group: 'a', sort: 10 }); | ||
expect(other.nodes.join('')).to.equal('13579'); | ||
topo1.merge([topo2, null, other]); | ||
expect(topo1.nodes.join('')).to.equal('0213547869'); | ||
done(); | ||
}); | ||
it('throws on circular dependency', function (done) { | ||
var topo = new Topo(); | ||
topo.add('0', { before: 'a', group: 'b' }); | ||
topo.add('1', { before: 'c', group: 'a' }); | ||
var other = new Topo(); | ||
other.add('2', { before: 'b', group: 'c' }); | ||
expect(function () { | ||
topo.merge(other); | ||
}).to.throw('merge created a dependencies error'); | ||
done(); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
19920
9
367
0
30