Skip to content
This repository was archived by the owner on Aug 11, 2021. It is now read-only.

Commit

Permalink
feat: remove cloning
Browse files Browse the repository at this point in the history
BREAKING CHANGE: `DAGNode.clone()` is removed from public API without any replacement.

Also the API for `rmLink()` and `addLink()` changed. They no longer
return a new node, but just remove/add the links to/from the current
node.

Prior to this change:

    const lessLinks = DAGNode.rmLink(node1, 'Link1')
    node1 = lessLinks
    const moreLinks = await DAGNode.addLink(node2, link)
    node2 = moreLinks

Now:

    DAGNode.rmLink(node, 'Link1')
    await DAGNode.addLink(node2, link)
  • Loading branch information
vmx committed Jul 19, 2019
1 parent 8630de5 commit d5e1135
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 127 deletions.
31 changes: 8 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
- [DAGNode.create(data, links)](#dagnodecreatedata-links)
- [addLink(node, link)](#addlinknode-link)
- [rmLink(node, nameOrCid)](#rmlinknode-nameorcid)
- [clone(node)](#clonenode)
- [DAGNode instance methods and properties](#dagnode-instance-methods-and-properties)
- [`node.Data`](#nodedata)
- [`node.Links`](#nodelinks)
Expand Down Expand Up @@ -67,7 +66,6 @@
const dagPB = require('ipld-dag-pb')

dagPB.DAGNode.create // create a DAGNode
dagPB.DAGNode.clone // clone a DAGNode
dagPB.DAGNode.addLink // add a Link to a DAGNode, creating a new one
dagPB.DAGNode.rmLink // remove a Link to a DAGNode, creating a new one

Expand Down Expand Up @@ -96,13 +94,11 @@ const link = {
Tsize: 42
}

const nodeA = await DAGNode.addLink(node, link)
// nodeA - DAGNode instance with the link
console.log('with link', nodeA.toJSON())
await DAGNode.addLink(node, link)
console.log('with link', node.toJSON())

const nodeB = await DAGNode.rmLink(nodeA, 'I am a link')
// nodeB - DAGNode instance without the link, equal to just node
console.log('without link', nodeB.toJSON())
DAGNode.rmLink(nodeA, 'I am a link')
console.log('now without link', node.toJSON())
```

## API
Expand Down Expand Up @@ -144,9 +140,7 @@ links can be a single or an array of DAGLinks instances or objects with the foll
- `node` - type: DAGNode
- `link` - type: DAGLink or DAGLink in its json format

Creates a link on node A to node B by using node B to get its CID. Returns a *new* instance of DAGNode without modifying the old one.

Creates a new DAGNode instance with the union of node.links plus the new link.
Creates a link on node A. Modifies the node.

`link` can be:
- DAGLink instance
Expand All @@ -160,29 +154,20 @@ const link = {
Hash: <cid> // can be a String CID, CID buffer or CID object
}

const dagNode = await DAGNode.addLink(node, link)
await DAGNode.addLink(node, link)
```

#### rmLink(node, nameOrCid)

- `node` - type: DAGNode
- `nameOrCid` - type: String, CID object or CID buffer

Removes a link from the node by name. Returns a *new* instance of DAGNode without modifying the old one.
Removes a link from the node by name. Modifies the node.

```JavaScript
const dagNode = await DAGNode.rmLink(node, 'Link1')
DAGNode.rmLink(node, 'Link1')
```

#### clone(node)

- `node` - type: DAGNode

Creates a clone of the DAGNode instance passed

```JavaScript
const nodeClone = DAGNode.clone(node)
```

### DAGNode instance methods and properties

Expand Down
18 changes: 6 additions & 12 deletions src/dag-node/addLink.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
'use strict'

const dagNodeUtil = require('./util')
const cloneLinks = dagNodeUtil.cloneLinks
const cloneData = dagNodeUtil.cloneData
const toDAGLink = dagNodeUtil.toDAGLink
const DAGLink = require('../dag-link/dagLink')
const DAGNode = require('./dagNode')
const create = require('./create')
const sort = require('stable')
const { linkSort, toDAGLink } = require('./util')
const DAGLink = require('../dag-link')
const DAGNode = require('./index')

// Intentionally keeping the `async` to signal that it may return a promise
// eslint-disable-next-line require-await
Expand All @@ -28,12 +25,9 @@ const asDAGLink = async (link) => {
}

const addLink = async (node, link) => {
const links = cloneLinks(node)
const data = cloneData(node)

const dagLink = await asDAGLink(link)
links.push(dagLink)
return create(data, links)
node._links.push(dagLink)
node._links = sort(node._links, linkSort)
}

module.exports = addLink
14 changes: 0 additions & 14 deletions src/dag-node/clone.js

This file was deleted.

1 change: 0 additions & 1 deletion src/dag-node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@

exports = module.exports = require('./dagNode')
exports.create = require('./create')
exports.clone = require('./clone')
exports.addLink = require('./addLink')
exports.rmLink = require('./rmLink')
15 changes: 4 additions & 11 deletions src/dag-node/rmLink.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
'use strict'

const dagNodeUtil = require('./util')
const cloneLinks = dagNodeUtil.cloneLinks
const cloneData = dagNodeUtil.cloneData
const create = require('./create')
const CID = require('cids')

const rmLink = (dagNode, nameOrCid) => {
const data = cloneData(dagNode)
let links = cloneLinks(dagNode)

// It's a name
if (typeof nameOrCid === 'string') {
links = links.filter((link) => link.Name !== nameOrCid)
dagNode._links = dagNode._links.filter((link) => link.Name !== nameOrCid)
} else if (Buffer.isBuffer(nameOrCid) || CID.isCID(nameOrCid)) {
links = links.filter((link) => !link.Hash.equals(nameOrCid))
dagNode._links = dagNode._links.filter(
(link) => !link.Hash.equals(nameOrCid))
} else {
throw new Error('second arg needs to be a name or CID')
}

return create(data, links)
}

module.exports = rmLink
19 changes: 0 additions & 19 deletions src/dag-node/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,6 @@ const {

exports = module.exports

function cloneData (dagNode) {
let data

if (dagNode.Data && dagNode.Data.length > 0) {
data = Buffer.alloc(dagNode.Data.length)
dagNode.Data.copy(data)
} else {
data = Buffer.alloc(0)
}

return data
}

function cloneLinks (dagNode) {
return dagNode.Links.slice()
}

function linkSort (a, b) {
return Buffer.compare(a.nameAsBuffer, b.nameAsBuffer)
}
Expand All @@ -38,7 +21,5 @@ const toDAGLink = async (node, options = {}) => {
return new DAGLink(options.name || '', serialized.length, nodeCid)
}

exports.cloneData = cloneData
exports.cloneLinks = cloneLinks
exports.linkSort = linkSort
exports.toDAGLink = toDAGLink
96 changes: 49 additions & 47 deletions test/dag-node-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,106 +124,108 @@ module.exports = (repo) => {
})

it('addLink by DAGNode', async () => {
const node1a = DAGNode.create(Buffer.from('1'))
const node1 = DAGNode.create(Buffer.from('1'))
const node2 = DAGNode.create(Buffer.from('2'))
const node1b = await DAGNode.addLink(node1a, node2)
expect(node1b.Links.length).to.equal(1)
expect(node1b.Links[0].Tsize).to.eql(node2.size)
expect(node1b.Links[0].Name).to.be.eql('')
await DAGNode.addLink(node1, node2)
expect(node1.Links.length).to.equal(1)
expect(node1.Links[0].Tsize).to.eql(node2.size)
expect(node1.Links[0].Name).to.be.eql('')
})

it('addLink by DAGLink', async () => {
const node1a = DAGNode.create(Buffer.from('1'))
const node1 = DAGNode.create(Buffer.from('1'))
const node2 = DAGNode.create(Buffer.from('2'))
const link = await toDAGLink(node2)
const node1b = await DAGNode.addLink(node1a, link)
expect(node1b.Links.length).to.equal(1)
expect(node1b.Links[0].Tsize).to.eql(node2.size)
expect(node1b.Links[0].Name).to.be.eql('')
await DAGNode.addLink(node1, link)
expect(node1.Links.length).to.equal(1)
expect(node1.Links[0].Tsize).to.eql(node2.size)
expect(node1.Links[0].Name).to.be.eql('')
})

it('addLink by object', async () => {
const node1a = DAGNode.create(Buffer.from('1'))
const node1 = DAGNode.create(Buffer.from('1'))
const node2 = DAGNode.create(Buffer.from('2'))
const link = await toDAGLink(node2)
const linkObject = link.toJSON()
const node1b = await DAGNode.addLink(node1a, linkObject)
expect(node1b.Links.length).to.equal(1)
expect(node1b.Links[0].Tsize).to.eql(node2.size)
expect(node1b.Links[0].Name).to.be.eql('')
await DAGNode.addLink(node1, linkObject)
expect(node1.Links.length).to.equal(1)
expect(node1.Links[0].Tsize).to.eql(node2.size)
expect(node1.Links[0].Name).to.be.eql('')
})

it('addLink by name', async () => {
const node1a = DAGNode.create(Buffer.from('1'))
const node1 = DAGNode.create(Buffer.from('1'))
const node2 = DAGNode.create(Buffer.from('2'))
const link = await toDAGLink(node2, { name: 'banana' })
expect(Object.keys(node1a)).to.not.include('banana')
const node1b = await DAGNode.addLink(node1a, link)
expect(node1b.Links.length).to.equal(1)
expect(node1b.Links[0].Tsize).to.eql(node2.size)
expect(node1b.Links[0].Name).to.eql('banana')
expect(node1.Links.length).to.equal(0)
await DAGNode.addLink(node1, link)
expect(node1.Links.length).to.equal(1)
expect(node1.Links[0].Tsize).to.eql(node2.size)
expect(node1.Links[0].Name).to.eql('banana')
})

it('addLink - add several links', async () => {
const node1a = DAGNode.create(Buffer.from('1'))
expect(node1a.Links.length).to.equal(0)
const node1 = DAGNode.create(Buffer.from('1'))
expect(node1.Links.length).to.equal(0)

const node2 = DAGNode.create(Buffer.from('2'))
const node1b = await DAGNode.addLink(node1a, node2)
expect(node1b.Links.length).to.equal(1)
await DAGNode.addLink(node1, node2)
expect(node1.Links.length).to.equal(1)

const node3 = DAGNode.create(Buffer.from('3'))
const node1c = await DAGNode.addLink(node1b, node3)
expect(node1c.Links.length).to.equal(2)
await DAGNode.addLink(node1, node3)
expect(node1.Links.length).to.equal(2)
})

it('addLink by DAGNode.Links', async () => {
const linkName = 'link-name'
const remote = DAGNode.create(Buffer.from('2'))
const source = await DAGNode.addLink(
DAGNode.create(Buffer.from('1')), await toDAGLink(remote, {
const source = DAGNode.create(Buffer.from('1'))
await DAGNode.addLink(
source,
await toDAGLink(remote, {
name: linkName
})
)

expect(source.Links.length).to.equal(1)

let target = new DAGNode(null, [], 0)
target = await DAGNode.addLink(target, source.Links[0])
const target = new DAGNode(null, [], 0)
await DAGNode.addLink(target, source.Links[0])

expect(target.Links.length).to.equal(1)
expect(target.Links[0].Tsize).to.eql(remote.size)
expect(target.Links[0].Name).to.be.eql(linkName)
})

it('rmLink by name', async () => {
const node1a = DAGNode.create(Buffer.from('1'))
expect(node1a.Links.length).to.eql(0)
const withoutLink = node1a.toJSON()
const node1 = DAGNode.create(Buffer.from('1'))
expect(node1.Links.length).to.eql(0)
const withoutLink = node1.toJSON()

const node2 = DAGNode.create(Buffer.from('2'))
const link = await toDAGLink(node2, { name: 'banana' })

const node1b = await DAGNode.addLink(node1a, link)
expect(node1b.Links.length).to.eql(1)
const node1c = DAGNode.rmLink(node1b, 'banana')
expect(node1c.Links.length).to.eql(0)
expect(node1c.toJSON()).to.eql(withoutLink)
await DAGNode.addLink(node1, link)
expect(node1.Links.length).to.eql(1)
DAGNode.rmLink(node1, 'banana')
expect(node1.Links.length).to.eql(0)
expect(node1.toJSON()).to.eql(withoutLink)
})

it('rmLink by hash', async () => {
const node1a = DAGNode.create(Buffer.from('1'))
expect(node1a.Links.length).to.eql(0)
const withoutLink = node1a.toJSON()
const node1 = DAGNode.create(Buffer.from('1'))
expect(node1.Links.length).to.eql(0)
const withoutLink = node1.toJSON()

const node2 = DAGNode.create(Buffer.from('2'))
const link = await toDAGLink(node2, { name: 'banana' })

const node1b = await DAGNode.addLink(node1a, link)
expect(node1b.Links.length).to.eql(1)
const node1c = DAGNode.rmLink(node1b, node1b.Links[0].Hash)
expect(node1c.Links.length).to.eql(0)
expect(node1c.toJSON()).to.eql(withoutLink)
await DAGNode.addLink(node1, link)
expect(node1.Links.length).to.eql(1)
DAGNode.rmLink(node1, node1.Links[0].Hash)
expect(node1.Links.length).to.eql(0)
expect(node1.toJSON()).to.eql(withoutLink)
})

it('get node CID', async () => {
Expand Down

0 comments on commit d5e1135

Please sign in to comment.