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

Commit 945fc61

Browse files
committed
feat: add single item functions
BREAKING CHANGE: put/get/remove functions are renamed This commit introduces single item functions which are called `put()`/`get()`,`remove()`. In order to put, get or remove multiple items you need to call `putMany()`,`getMany()`/`removeMany()` now.
1 parent 43176ca commit 945fc61

File tree

11 files changed

+156
-147
lines changed

11 files changed

+156
-147
lines changed

src/index.js

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -127,42 +127,94 @@ class IPLDResolver {
127127
return extendIterator(generator())
128128
}
129129

130+
/**
131+
* Get a node by CID.
132+
*
133+
* @param {CID} cid - The CID of the IPLD Node that should be retrieved.
134+
* @returns {Promise.<Object>} - Returns a Promise with the IPLD Node that correspond to the given `cid`.
135+
*/
136+
async get (cid) {
137+
const block = await promisify(this.bs.get.bind(this.bs))(cid)
138+
const format = await this._getFormat(block.cid.codec)
139+
const node = await promisify(format.util.deserialize)(block.data)
140+
141+
return node
142+
}
143+
130144
/**
131145
* Get multiple nodes back from an array of CIDs.
132146
*
133147
* @param {Iterable.<CID>} cids - The CIDs of the IPLD Nodes that should be retrieved.
134148
* @returns {Iterable.<Promise.<Object>>} - Returns an async iterator with the IPLD Nodes that correspond to the given `cids`.
135149
*/
136-
get (cids) {
150+
getMany (cids) {
137151
if (!typical.isIterable(cids) || typical.isString(cids) ||
138152
Buffer.isBuffer(cids)) {
139153
throw new Error('`cids` must be an iterable of CIDs')
140154
}
141155

142156
const generator = async function * () {
143157
for await (const cid of cids) {
144-
const block = await promisify(this.bs.get.bind(this.bs))(cid)
145-
const format = await this._getFormat(block.cid.codec)
146-
const node = await promisify(format.util.deserialize)(block.data)
147-
yield node
158+
yield this.get(cid)
148159
}
149160
}.bind(this)
150161

151162
return extendIterator(generator())
152163
}
153164

165+
/**
166+
* Stores the given IPLD Node of a recognized IPLD Format.
167+
*
168+
* @param {Object} node - The deserialized IPLD node that should be inserted.
169+
* @param {number} format - The multicodec of the format that IPLD Node should be encoded in.
170+
* @param {Object} [userOptions] - Options is an object with the following properties.
171+
* @param {number} [userOtions.hashAlg=hash algorithm of the given multicodec] - The hashing algorithm that is used to calculate the CID.
172+
* @param {number} [userOptions.cidVersion=1] - The CID version to use.
173+
* @param {boolean} [userOptions.onlyHash=false] - If true the serialized form of the IPLD Node will not be passed to the underlying block store.
174+
* @returns {Promise.<CID>} - Returns the CID of the serialized IPLD Nodes.
175+
*/
176+
async put (node, format, userOptions) {
177+
if (format === undefined) {
178+
throw new Error('`put` requires a format')
179+
}
180+
if (typeof format !== 'number') {
181+
throw new Error('`format` parameter must be number (multicodec)')
182+
}
183+
184+
const formatImpl = await this._getFormat(format)
185+
const defaultOptions = {
186+
hashAlg: formatImpl.defaultHashAlg,
187+
cidVersion: 1,
188+
onlyHash: false
189+
}
190+
const options = mergeOptions(defaultOptions, userOptions)
191+
192+
const cidOptions = {
193+
version: options.cidVersion,
194+
hashAlg: options.hashAlg,
195+
onlyHash: options.onlyHash
196+
}
197+
const cid = await promisify(formatImpl.util.cid)(node, cidOptions)
198+
199+
if (!options.onlyHash) {
200+
await this._store(cid, node)
201+
}
202+
203+
return cid
204+
}
205+
154206
/**
155207
* Stores the given IPLD Nodes of a recognized IPLD Format.
156208
*
157209
* @param {Iterable.<Object>} nodes - Deserialized IPLD nodes that should be inserted.
158210
* @param {number} format - The multicodec of the format that IPLD Node should be encoded in.
159211
* @param {Object} [userOptions] - Options are applied to any of the `nodes` and is an object with the following properties.
160212
* @param {number} [userOtions.hashAlg=hash algorithm of the given multicodec] - The hashing algorithm that is used to calculate the CID.
161-
* @param {number} [userOptions.cidVersion=1]`- The CID version to use.
213+
* @param {number} [userOptions.cidVersion=1] - The CID version to use.
162214
* @param {boolean} [userOptions.onlyHash=false] - If true the serialized form of the IPLD Node will not be passed to the underlying block store.
163215
* @returns {Iterable.<Promise.<CID>>} - Returns an async iterator with the CIDs of the serialized IPLD Nodes.
164216
*/
165-
put (nodes, format, userOptions) {
217+
putMany (nodes, format, userOptions) {
166218
if (!typical.isIterable(nodes) || typical.isString(nodes) ||
167219
Buffer.isBuffer(nodes)) {
168220
throw new Error('`nodes` must be an iterable')
@@ -192,41 +244,41 @@ class IPLDResolver {
192244
options = mergeOptions(defaultOptions, userOptions)
193245
}
194246

195-
const cidOptions = {
196-
version: options.cidVersion,
197-
hashAlg: options.hashAlg,
198-
onlyHash: options.onlyHash
199-
}
200-
const cid = await promisify(formatImpl.util.cid)(node, cidOptions)
201-
if (!options.onlyHash) {
202-
await this._store(cid, node)
203-
}
204-
yield cid
247+
yield this.put(node, format, options)
205248
}
206249
}.bind(this)
207250

208251
return extendIterator(generator())
209252
}
210253

254+
/**
255+
* Remove an IPLD Node by the given CID.
256+
*
257+
* @param {CID} cid - The CID of the IPLD Node that should be removed.
258+
* @return {Promise.<CID>} The CID of the removed IPLD Node.
259+
*/
260+
async remove (cid) {
261+
return promisify(this.bs.delete.bind(this.bs))(cid)
262+
}
263+
211264
/**
212265
* Remove IPLD Nodes by the given CIDs.
213266
*
214267
* Throws an error if any of the Blocks can’t be removed. This operation is
215268
* *not* atomic, some Blocks might have already been removed.
216269
*
217-
* @param {Iterable.<CID>} cids - The CIDs of the IPLD Nodes that should be removed
218-
* @return {void}
270+
* @param {Iterable.<CID>} cids - The CIDs of the IPLD Nodes that should be removed.
271+
* @return {Iterable.<Promise.<CID>>} Returns an async iterator with the CIDs of the removed IPLD Nodes.
219272
*/
220-
remove (cids) {
273+
removeMany (cids) {
221274
if (!typical.isIterable(cids) || typical.isString(cids) ||
222275
Buffer.isBuffer(cids)) {
223276
throw new Error('`cids` must be an iterable of CIDs')
224277
}
225278

226279
const generator = async function * () {
227280
for await (const cid of cids) {
228-
await promisify(this.bs.delete.bind(this.bs))(cid)
229-
yield cid
281+
yield this.remove(cid)
230282
}
231283
}.bind(this)
232284

test/basics.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,29 @@ module.exports = (repo) => {
5353
const bs = new BlockService(repo)
5454
const r = new IPLDResolver({ blockService: bs })
5555
// choosing a format that is not supported
56-
const result = r.put([null], multicodec.BLAKE2B_8)
56+
await expect(r.put(null, multicodec.BLAKE2B_8)).to.be.rejectedWith(
57+
'No resolver found for codec "blake2b-8"')
58+
})
59+
60+
it('put - errors if no format is provided', async () => {
61+
const bs = new BlockService(repo)
62+
const r = new IPLDResolver({ blockService: bs })
63+
await expect(r.put(null)).to.be.rejectedWith('`put` requires a format')
64+
})
65+
66+
it('putMany - errors on unknown resolver', async () => {
67+
const bs = new BlockService(repo)
68+
const r = new IPLDResolver({ blockService: bs })
69+
// choosing a format that is not supported
70+
const result = r.putMany([null], multicodec.BLAKE2B_8)
5771
await expect(result.next()).to.be.rejectedWith(
5872
'No resolver found for codec "blake2b-8"')
5973
})
6074

61-
it('put - errors if no format is provided', () => {
75+
it('putMany - errors if no format is provided', () => {
6276
const bs = new BlockService(repo)
6377
const r = new IPLDResolver({ blockService: bs })
64-
expect(() => r.put([null])).to.be.throw('`put` requires a format')
78+
expect(() => r.putMany([null])).to.be.throw('`put` requires a format')
6579
})
6680

6781
it('tree - errors on unknown resolver', async () => {

test/format-support.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ module.exports = (repo) => {
2323

2424
data = { now: Date.now() }
2525

26-
const result = resolver.put([data], multicodec.DAG_CBOR)
27-
cid = await result.last()
26+
cid = await resolver.put(data, multicodec.DAG_CBOR)
2827
})
2928

3029
describe('Dynamic format loading', () => {

test/ipld-all.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ describe('IPLD Resolver for dag-cbor + dag-pb', () => {
5858
{ node: nodePb, format: multicodec.DAG_PB, cidVersion: 0 },
5959
{ node: nodeCbor, format: multicodec.DAG_CBOR, cidVersion: 1 }
6060
], (nac, cb) => {
61-
resolver.put([nac.node], nac.format, {
61+
resolver.put(nac.node, nac.format, {
6262
cidVersion: nac.cidVersion
63-
}).first().then(
63+
}).then(
6464
() => cb(null),
6565
(error) => cb(error)
6666
)
@@ -84,12 +84,11 @@ describe('IPLD Resolver for dag-cbor + dag-pb', () => {
8484
waterfall([
8585
(cb) => dagPB.DAGNode.create(Buffer.from('Some data here'), cb),
8686
(node, cb) => {
87-
const result = resolver.put([node], multicodec.DAG_PB, {
87+
resolver.put(node, multicodec.DAG_PB, {
8888
onlyHash: true,
8989
cidVersion: 1,
9090
hashAlg: multicodec.SHA2_256
91-
})
92-
result.first().then(
91+
}).then(
9392
(cid) => cb(null, cid),
9493
(error) => cb(error)
9594
)
@@ -107,21 +106,21 @@ describe('IPLD Resolver for dag-cbor + dag-pb', () => {
107106

108107
describe('get', () => {
109108
it('should return nodes correctly', async () => {
110-
const result = resolver.get([cidCbor, cidPb])
109+
const result = resolver.getMany([cidCbor, cidPb])
111110
const [node1, node2] = await result.all()
112111
expect(node1).to.eql(nodeCbor)
113112
expect(node2).to.eql(nodePb)
114113
})
115114

116115
it('should return nodes in input order', async () => {
117-
const result = resolver.get([cidPb, cidCbor])
116+
const result = resolver.getMany([cidPb, cidCbor])
118117
const [node1, node2] = await result.all()
119118
expect(node1).to.eql(nodePb)
120119
expect(node2).to.eql(nodeCbor)
121120
})
122121

123122
it('should return error on invalid CID', async () => {
124-
const result = resolver.get([cidCbor, 'invalidcid'])
123+
const result = resolver.getMany([cidCbor, 'invalidcid'])
125124
// First node is valid
126125
await result.next()
127126
// Second one is not
@@ -131,15 +130,15 @@ describe('IPLD Resolver for dag-cbor + dag-pb', () => {
131130
it('should return error on non-existent CID', async () => {
132131
const nonExistentCid = new CID(
133132
'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP')
134-
const result = resolver.get([cidCbor, nonExistentCid])
133+
const result = resolver.getMany([cidCbor, nonExistentCid])
135134
// First node is valid
136135
await result.next()
137136
// Second one is not
138137
await expect(result.next()).to.be.rejectedWith('Not Found')
139138
})
140139

141140
it('should return error on invalid input', () => {
142-
expect(() => resolver.get('astring')).to.throw(
141+
expect(() => resolver.getMany('astring')).to.throw(
143142
'`cids` must be an iterable of CIDs')
144143
})
145144
})

test/ipld-bitcoin.js

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ module.exports = (repo) => {
8484

8585
async function store () {
8686
const nodes = [node1, node2, node3]
87-
const result = resolver.put(nodes, multicodec.BITCOIN_BLOCK)
87+
const result = resolver.putMany(nodes, multicodec.BITCOIN_BLOCK)
8888
;[cid1, cid2, cid3] = await result.all()
8989

9090
done()
@@ -93,8 +93,7 @@ module.exports = (repo) => {
9393

9494
describe('public api', () => {
9595
it('resolver.put with format', async () => {
96-
const result = resolver.put([node1], multicodec.BITCOIN_BLOCK)
97-
const cid = await result.first()
96+
const cid = await resolver.put(node1, multicodec.BITCOIN_BLOCK)
9897
expect(cid.version).to.equal(1)
9998
expect(cid.codec).to.equal('bitcoin-block')
10099
expect(cid.multihash).to.exist()
@@ -103,10 +102,9 @@ module.exports = (repo) => {
103102
})
104103

105104
it('resolver.put with format + hashAlg', async () => {
106-
const result = resolver.put([node1], multicodec.BITCOIN_BLOCK, {
105+
const cid = await resolver.put(node1, multicodec.BITCOIN_BLOCK, {
107106
hashAlg: multicodec.SHA3_512
108107
})
109-
const cid = await result.first()
110108
expect(cid.version).to.equal(1)
111109
expect(cid.codec).to.equal('bitcoin-block')
112110
expect(cid.multihash).to.exist()
@@ -147,28 +145,21 @@ module.exports = (repo) => {
147145
})
148146

149147
it('resolver.get round-trip', async () => {
150-
const resultPut = resolver.put([node1], multicodec.BITCOIN_BLOCK)
151-
const cid = await resultPut.first()
152-
const resultGet = resolver.get([cid])
153-
const node = await resultGet.first()
148+
const cid = await resolver.put(node1, multicodec.BITCOIN_BLOCK)
149+
const node = await resolver.get(cid)
154150
expect(node).to.deep.equal(node1)
155151
})
156152

157153
it('resolver.remove', async () => {
158-
const resultPut = resolver.put([node1], multicodec.BITCOIN_BLOCK)
159-
const cid = await resultPut.first()
160-
const resultGet = resolver.get([cid])
161-
const sameAsNode1 = await resultGet.first()
154+
const cid = await resolver.put(node1, multicodec.BITCOIN_BLOCK)
155+
const sameAsNode1 = await resolver.get(cid)
162156
expect(sameAsNode1).to.deep.equal(node1)
163157
return remove()
164158

165159
async function remove () {
166-
const resultRemove = resolver.remove([cid])
167-
// The items are deleted through iteration
168-
await resultRemove.last()
160+
await resolver.remove(cid)
169161
// Verify that the item got really deleted
170-
const resultGet = resolver.get([cid])
171-
await expect(resultGet.next()).to.eventually.be.rejected()
162+
await expect(resolver.get(cid)).to.eventually.be.rejected()
172163
}
173164
})
174165
})

0 commit comments

Comments
 (0)