@tangle/reduce
Advanced tools
Comparing version 3.1.0 to 4.0.0
39
index.js
@@ -10,14 +10,9 @@ const Graph = require('@tangle/graph') | ||
nodes = [], | ||
getTransformation = (node, distance) => node, | ||
getBacklinks = node => node.previous, | ||
isValid | ||
} = opts | ||
// TODO prune time-travellers | ||
this.graph = new Graph(nodes, { getBacklinks }) | ||
this.graph = new Graph(nodes) | ||
this.isValid = isValid | ||
this.getT = (nodeId, distance) => { | ||
return strategy.mapToPure( | ||
getTransformation(this.graph.getNode(nodeId), distance) | ||
) | ||
return strategy.mapToPure(this.graph.getNode(nodeId).data, distance) | ||
} | ||
@@ -38,3 +33,3 @@ | ||
const queue = new Queue() | ||
// a queue made up of objects { nodeId, accT, d } representing position in graph: | ||
// a queue made up of objects { nodeId, accT, d, nodeHistory } representing position in graph: | ||
// - nodeId = the unique identifier for a node | ||
@@ -65,3 +60,3 @@ // - accT = the accumulated (concat'd) Transformation up to and including node `nodeId` | ||
preMerge: new Map(), | ||
// a Map of form { [nodeId]: accT } | ||
// a Map of form { [nodeId]: {accT, d} } | ||
// which describes the nodes immediately preceeding a merge-node | ||
@@ -117,3 +112,19 @@ terminal: {} | ||
const mergeTransformation = getT(nextId, maxD + 1) | ||
// TODO: Use getT to ensure that we can get to the fields we want | ||
if (strategy.isValidMerge(graph, nextId)) { | ||
queue.add({ | ||
nodeId: nextId, | ||
accT: strategy.merge(graph, nextId), | ||
d: maxD + 1 | ||
}) | ||
} else { | ||
// The next node is not a valid merge | ||
graph.invalidateKeys([nextId]) | ||
// Need to check if tips.premerge nodes are now terminal | ||
requiredNodeIds.forEach(prevId => { | ||
if (graph.isTipNode(prevId)) { | ||
tips.terminal[prevId] = tips.preMerge.get(prevId).accT | ||
} | ||
}) | ||
} | ||
@@ -146,8 +157,4 @@ // const preMergeTransformations = requiredNodeIds.map(nodeId => tips.preMerge.get(nodeId).accT) | ||
queue.add({ | ||
nodeId: nextId, | ||
// accT: nextT | ||
accT: mergeTransformation, | ||
d: maxD + 1 | ||
}) | ||
// nodeHistory should include it's branchHistories plus nextId | ||
// this just treats merge like an overwrite (ignoring all transformations so far) | ||
@@ -154,0 +161,0 @@ // and for all properties, which is wrong because it ignores invalid merges, and over-writes un-named values with identity |
{ | ||
"name": "@tangle/reduce", | ||
"version": "3.1.0", | ||
"version": "4.0.0", | ||
"description": "reduce tangles into their current state", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "tape test/*.test.js | faucet", | ||
"test": "npm run test:js && npm run lint", | ||
"test:js": "tape test/*.test.js | tap-spec", | ||
"lint": "standard --fix" | ||
@@ -26,12 +27,12 @@ }, | ||
"devDependencies": { | ||
"@tangle/overwrite": "^2.0.0", | ||
"@tangle/simple-set": "^2.0.0", | ||
"@tangle/strategy": "^2.0.1", | ||
"faucet": "0.0.1", | ||
"@tangle/overwrite": "^2.1.0", | ||
"@tangle/simple-set": "^2.1.0", | ||
"@tangle/strategy": "^3.0.0", | ||
"standard": "^16.0.3", | ||
"tap-spec": "^5.0.0", | ||
"tape": "^5.0.1" | ||
}, | ||
"dependencies": { | ||
"@tangle/graph": "^2.1.0" | ||
"@tangle/graph": "^3.0.0" | ||
} | ||
} |
@@ -25,4 +25,6 @@ # @tangle/reduce | ||
previous: null, | ||
title: { set: 'spec gathering' }, | ||
attendees: { mix: 1, luandro: 1 } | ||
data: { | ||
title: { set: 'spec gathering' }, | ||
attendees: { mix: 1, luandro: 1 } | ||
} | ||
}, | ||
@@ -32,3 +34,3 @@ { | ||
previous: ['A'], | ||
attendees: { luandro: -1, cherese: 1 } | ||
data: {attendees: { luandro: -1, cherese: 1 }} | ||
}, | ||
@@ -38,3 +40,5 @@ { | ||
previous: ['A'], | ||
attendees: { luandro: -1 } | ||
data: { | ||
attendees: { luandro: -1 } | ||
} | ||
}, | ||
@@ -44,3 +48,5 @@ { | ||
previous: ['B', 'C'], | ||
title: { set: 'Tangle Spec v1 meeting' }, | ||
data: { | ||
title: { set: 'Tangle Spec v1 meeting' } | ||
} | ||
}, | ||
@@ -73,3 +79,3 @@ ] | ||
Note you could use `strategy.mapToOutput` to convert this accumulated transformation | ||
into a 'real' state: | ||
into a 'real' state: | ||
@@ -94,21 +100,6 @@ ```js | ||
- `opts.nodes` *Array* is a collection of tangle nodes, where each expected to include: | ||
- `node.key` - a unique identified for the node | ||
- "backlinks" | ||
- an Array of keys for nodes which this node extended from (or `null` if it's a root node) | ||
- default location: `node.previous` (can be over-ridden with `opts.getBacklinks`) | ||
- "transformation" | ||
- an object which containing the transformation which the `strategy` describes | ||
- default location: `node` (can be over-ridden with `opts.getTransformation`) | ||
- `node.key` - a unique identifier for the node | ||
- `node.previous` - an Array of keys for nodes which this node extended from | ||
- `node.data` - an object which contains the transformation which the `strategy` describes | ||
- `opts.getBacklinks = fn(node): Array` | ||
- fetch the part of the node which contains the backlinks to the nodes it followed in the tangle | ||
- default: `node => node.previous` | ||
- `opts.getTransformation = fn(node, distance): Object` | ||
- fetch the part of the node which contains the transformation | ||
- `node` - raw node from which you are going to extract a transformation, `T` | ||
- `distance` - an integer describing how far the node is from the root (this is a monotonically increasing number so a merge nodes distance will always be 1 greater than the maximum of it's backlinks distances) | ||
- default: `(node, distance) => node` | ||
- NOTE - the strategy will automatically pick out properties defined in the strategy and ignore all others | ||
- `opts.isValid = fn(context, node): Boolean` | ||
@@ -119,3 +110,3 @@ - determine whether the next node `node` should be included in the tangle | ||
- `accT` is the accumulated transform right before `node` | ||
- NOTE if a node is not valid, all nodes downstream of that node and considered invalid, and will not be included in the reduce | ||
- NOTE if a node is not valid, all nodes downstream of that node and considered invalid, and will not be included in the reduce | ||
@@ -133,3 +124,1 @@ | ||
Register more nodes to include in the reducing. | ||
@@ -23,3 +23,3 @@ const test = require('tape') | ||
key: 'A', | ||
author: '@mix', | ||
data: { author: '@mix' }, | ||
previous: null | ||
@@ -29,5 +29,7 @@ } | ||
key: 'B', | ||
author: '@stranger', | ||
previous: ['A'], | ||
title: { set: 'nice nice' } | ||
data: { | ||
author: '@stranger', | ||
title: { set: 'nice nice' } | ||
}, | ||
previous: ['A'] | ||
} | ||
@@ -53,4 +55,6 @@ | ||
key: 'C', | ||
author: '@mix', | ||
title: { set: 'another root' }, | ||
data: { | ||
author: '@mix', | ||
title: { set: 'another root' } | ||
}, | ||
previous: null | ||
@@ -84,4 +88,6 @@ } | ||
key: 'A', | ||
author: '@mix', | ||
title: { set: 'initial' }, | ||
data: { | ||
author: '@mix', | ||
title: { set: 'initial' } | ||
}, | ||
previous: null | ||
@@ -91,11 +97,15 @@ } | ||
key: 'B', | ||
author: '@stranger', | ||
previous: ['A'], | ||
title: { set: 'nice nice' } | ||
data: { | ||
author: '@stranger', | ||
title: { set: 'nice nice' } | ||
}, | ||
previous: ['A'] | ||
} | ||
const C = { | ||
key: 'C', | ||
author: '@stranger', | ||
previous: ['B'], | ||
title: { set: 'final' } | ||
data: { | ||
author: '@stranger', | ||
title: { set: 'final' } | ||
}, | ||
previous: ['B'] | ||
} | ||
@@ -102,0 +112,0 @@ |
@@ -19,7 +19,7 @@ const test = require('tape') | ||
const isAuthor = graph.rootNodes.some(rootNode => rootNode.author === nextNode.author) | ||
const isAuthor = graph.rootNodes.some(rootNode => rootNode.data.author === nextNode.data.author) | ||
if (isAuthor) return true | ||
const isOtherAuthor = nextNode.previous.every(key => { | ||
return accT.otherAuthors[nextNode.author] > 0 | ||
return accT.otherAuthors[nextNode.data.author] > 0 | ||
// look at this nodes reporte previous nodes | ||
@@ -45,17 +45,23 @@ // see if the accumulated Transformation state (accT) for that node | ||
key: 'A', | ||
author: '@mix', | ||
previous: null, | ||
title: { set: 'my root message' } | ||
data: { | ||
author: '@mix', | ||
title: { set: 'my root message' } | ||
}, | ||
previous: null | ||
} | ||
const B = { | ||
key: 'B', | ||
author: '@cherese', | ||
previous: ['A'], | ||
title: { set: 'nice nice' } | ||
data: { | ||
author: '@cherese', | ||
title: { set: 'nice nice' } | ||
}, | ||
previous: ['A'] | ||
} | ||
const C = { | ||
key: 'C', | ||
author: '@mix', | ||
previous: ['B'], | ||
title: { set: 'nice nice!!!!' } | ||
data: { | ||
author: '@mix', | ||
title: { set: 'nice nice!!!!' } | ||
}, | ||
previous: ['B'] | ||
} | ||
@@ -75,5 +81,7 @@ t.deepEqual( | ||
key: 'X', | ||
author: '@mix', | ||
title: { set: 'my root message' }, | ||
otherAuthors: { '@cherese': 1 }, | ||
data: { | ||
author: '@mix', | ||
title: { set: 'my root message' }, | ||
otherAuthors: { '@cherese': 1 } | ||
}, | ||
previous: null | ||
@@ -83,5 +91,7 @@ } | ||
key: 'Y', | ||
author: '@cherese', | ||
previous: ['X'], | ||
title: { set: 'nice nice' } | ||
data: { | ||
author: '@cherese', | ||
title: { set: 'nice nice' } | ||
}, | ||
previous: ['X'] | ||
} | ||
@@ -88,0 +98,0 @@ |
@@ -7,14 +7,5 @@ const test = require('tape') | ||
const StringAppendStrategy = () => ({ // stringAppend | ||
concat: (a, b) => a + b, | ||
identity: () => '', | ||
isConflict: (a, b) => a !== b, | ||
// conflictMerge: (merge, heads) => merge, | ||
mapToOutput: a => a, | ||
schema: { type: 'object' } | ||
}) | ||
const strategy = new Strategy({ | ||
title: OverwriteStrategy(), | ||
ouji: StringAppendStrategy() | ||
ouji: OverwriteStrategy() | ||
}) | ||
@@ -30,4 +21,6 @@ | ||
previous: null, | ||
title: { set: 'my root message' }, | ||
ouji: 'hello' | ||
data: { | ||
title: { set: 'my root message' }, | ||
ouji: { set: 'hello' } | ||
} | ||
} | ||
@@ -37,3 +30,3 @@ const B = { | ||
previous: ['A'], | ||
ouji: ' mix' | ||
data: { ouji: { set: 'mix' } } | ||
} | ||
@@ -43,4 +36,6 @@ const C = { | ||
previous: ['A'], | ||
title: { set: 'edited message' }, | ||
ouji: ' world' | ||
data: { | ||
title: { set: 'edited message' }, | ||
ouji: { set: 'world' } | ||
} | ||
} | ||
@@ -52,7 +47,7 @@ t.deepEqual( | ||
title: { set: 'my root message' }, | ||
ouji: 'hello mix' | ||
ouji: { set: 'mix' } | ||
}, | ||
C: { | ||
title: { set: 'edited message' }, | ||
ouji: 'hello world' | ||
ouji: { set: 'world' } | ||
} | ||
@@ -71,4 +66,6 @@ }, | ||
previous: ['B', 'C'], | ||
title: { set: 'edited and merged!' }, | ||
ouji: 'hello world (mix)' | ||
data: { | ||
title: { set: 'edited and merged!' }, | ||
ouji: { set: 'hello mix (world)' } | ||
} | ||
} | ||
@@ -83,3 +80,3 @@ // this is a valid merge because it resolves the conflict present between B + C | ||
title: { set: 'edited and merged!' }, | ||
ouji: 'hello world (mix)' | ||
ouji: { set: 'hello mix (world)' } | ||
} | ||
@@ -94,3 +91,3 @@ }, | ||
// TODO | ||
test('reduce (invalid merge)', { skip: true }, t => { | ||
test('reduce (invalid merge)', t => { | ||
// A (root) | ||
@@ -105,4 +102,6 @@ // / \ | ||
previous: null, | ||
title: { set: 'my root message' }, | ||
ouji: 'hello' | ||
data: { | ||
title: { set: 'my root message' }, | ||
ouji: { set: 'hello' } | ||
} | ||
} | ||
@@ -112,3 +111,3 @@ const B = { | ||
previous: ['A'], | ||
ouji: ' mix' | ||
data: { ouji: { set: 'mix' } } | ||
} | ||
@@ -118,4 +117,6 @@ const C = { | ||
previous: ['A'], | ||
title: { set: 'edited message' }, | ||
ouji: ' world' | ||
data: { | ||
title: { set: 'edited message' }, | ||
ouji: { set: 'world!' } | ||
} | ||
} | ||
@@ -125,4 +126,4 @@ const Dud = { | ||
previous: ['B', 'C'], | ||
title: { set: 'edited and merged!' } | ||
// ouji: identity() | ||
data: { title: { set: 'edited and merged!' } } | ||
// ouji: identity()} | ||
} | ||
@@ -137,7 +138,7 @@ // this is an invalid merge message because Dud fails to resolve conflict between B + C | ||
title: { set: 'my root message' }, | ||
ouji: 'hello mix' | ||
ouji: { set: 'mix' } | ||
}, | ||
C: { | ||
title: { set: 'edited message' }, | ||
ouji: 'hello world' | ||
ouji: { set: 'world!' } | ||
} | ||
@@ -152,3 +153,3 @@ }, | ||
// TODO | ||
test('reduce (automerge)', { skip: true }, t => { | ||
test('reduce (automerge)', t => { | ||
// A (root) | ||
@@ -165,4 +166,6 @@ // / \ | ||
previous: null, | ||
title: { set: 'my root message' }, | ||
ouji: 'hello' | ||
data: { | ||
title: { set: 'my root message' }, | ||
ouji: { set: 'hello' } | ||
} | ||
} | ||
@@ -172,4 +175,6 @@ const B = { | ||
previous: ['A'], | ||
title: { set: 'one two' }, | ||
ouji: ' mix' | ||
data: { | ||
title: { set: 'one two' }, | ||
ouji: { set: 'mix' } | ||
} | ||
} | ||
@@ -179,4 +184,6 @@ const C = { | ||
previous: ['A'], | ||
title: { set: 'one' }, | ||
ouji: ' world' | ||
data: { | ||
title: { set: 'one' }, | ||
ouji: { set: 'world' } | ||
} | ||
} | ||
@@ -186,3 +193,3 @@ const D = { | ||
previous: ['C'], | ||
title: { set: 'one two' } | ||
data: { title: { set: 'one two' } } | ||
} | ||
@@ -192,3 +199,3 @@ const E = { | ||
previous: ['B', 'D'], | ||
ouji: 'hello mix-world!' | ||
data: { ouji: { set: 'hello mix-world!' } } | ||
} | ||
@@ -203,4 +210,4 @@ // this is an valid because: | ||
E: { | ||
title: { set: 'my root message' }, | ||
ouji: 'hello mix-world!' | ||
title: { set: 'one two' }, | ||
ouji: { set: 'hello mix-world!' } | ||
} | ||
@@ -207,0 +214,0 @@ }, |
@@ -19,3 +19,3 @@ const test = require('tape') | ||
key: 'A', | ||
author: '@mix', | ||
data: { author: '@mix' }, | ||
previous: null | ||
@@ -25,5 +25,7 @@ } | ||
key: 'B', | ||
author: '@stranger', | ||
previous: ['A'], | ||
title: { set: 'nice nice' } | ||
data: { | ||
author: '@stranger', | ||
title: { set: 'nice nice' } | ||
}, | ||
previous: ['A'] | ||
} | ||
@@ -67,5 +69,7 @@ | ||
key: 'A', | ||
author: '@colin', | ||
previous: null, | ||
title: { set: 'What are people bringing to potluck?' } | ||
data: { | ||
author: '@colin', | ||
title: { set: 'What are people bringing to potluck?' } | ||
}, | ||
previous: null | ||
} | ||
@@ -75,26 +79,34 @@ | ||
key: 'B', | ||
author: '@rudeperson', | ||
previous: ['A'], | ||
menu: { pizza: 1 } | ||
data: { | ||
author: '@rudeperson', | ||
menu: { pizza: 1 } | ||
}, | ||
previous: ['A'] | ||
} | ||
const C = { | ||
key: 'C', | ||
author: '@glutenintolerant', | ||
previous: ['A'], | ||
menu: { salad: 1 }, | ||
comment: 'Nothing with gluten' | ||
data: { | ||
author: '@glutenintolerant', | ||
menu: { salad: 1 }, | ||
comment: 'Nothing with gluten' | ||
}, | ||
previous: ['A'] | ||
} | ||
const D = { | ||
key: 'D', | ||
author: '@rudeperson', | ||
previous: ['C'], | ||
menu: { pizza: -1 }, | ||
comment: 'whoops' | ||
data: { | ||
author: '@rudeperson', | ||
menu: { pizza: -1 }, | ||
comment: 'whoops' | ||
}, | ||
previous: ['C'] | ||
} | ||
const E = { | ||
key: 'E', | ||
author: '@someoneelse', | ||
previous: ['C'], | ||
title: { set: 'final menu' }, | ||
menu: { drinks: 1 } | ||
data: { | ||
author: '@someoneelse', | ||
title: { set: 'final menu' }, | ||
menu: { drinks: 1 } | ||
}, | ||
previous: ['C'] | ||
} | ||
@@ -101,0 +113,0 @@ console.warn('Start test') |
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
820
25120
9
117
+ Added@tangle/graph@3.2.0(transitive)
- Removed@tangle/graph@2.1.0(transitive)
Updated@tangle/graph@^3.0.0