Skip to content

Commit 47a7311

Browse files
committed
Merge pull request #5 from ipfs/feat/mfs
Feat/mfs
2 parents d881edf + b54d1d4 commit 47a7311

File tree

13 files changed

+443
-89
lines changed

13 files changed

+443
-89
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

.travis.yml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
sudo: false
2+
language: node_js
3+
node_js:
4+
- "4.0"
5+
6+
# Make sure we have new NPM.
7+
before_install:
8+
- npm install -g npm
9+
10+
script:
11+
- npm test

README.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1-
# ipfs-blob-store
1+
ipfs-blob-store
2+
===============
23

3-
Implements the [abstract-blob-store] API, built ontop of IPFS.
4+
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) ![Build Status](https://travis-ci.org/diasdavid/ipfs-blob-store.svg?style=flat-square)](https://travis-ci.org/diasdavid/ipfs-blob-store) ![](https://img.shields.io/badge/coverage-%3F-yellow.svg?style=flat-square) [![Dependency Status](https://david-dm.org/diasdavid/ipfs-blob-store.svg?style=flat-square)](https://david-dm.org/diasdavid/ipfs-blob-store) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
5+
6+
![](https://github.com/maxogden/abstract-blob-store/raw/master/badge.png)
7+
8+
> Implements the [abstract-blob-store](https://github.com/maxogden/abstract-blob-store) API, built on top of IPFS.
9+
10+
![](https://github.com/maxogden/abstract-blob-store/raw/master/badge.png)

examples/mfs-example.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
var ipfsBlobStore = require('../index.js')
2+
var store = ipfsBlobStore().mfs
3+
4+
/*
5+
process.stdin.pipe(store.createWriteStream('test/2/3/4', function (err, metadata) {
6+
if (err) {
7+
// console.log(err)
8+
}
9+
10+
console.log(metadata)
11+
}))
12+
*/
13+
14+
store.createReadStream('test/2/3/4').pipe(process.stdout)

index.js

+7-55
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,19 @@
11
var ipfs = require('ipfs-api')
2-
var stream = require('stream')
3-
var multihash = require('multihashes')
4-
var base58 = require('base58-native')
2+
var block = require('./lib/block')
3+
var dag = require('./lib/dag')
4+
var mfs = require('./lib/mfs')
55

66
module.exports = function (opts) {
77
if (!opts) opts = {}
88

99
opts.host = opts.host || '127.0.0.1'
1010
opts.port = opts.port || 5001
1111

12-
var store = {}
13-
1412
var node = ipfs(opts.host, opts.port)
1513

16-
store.createWriteStream = function (opts, cb) {
17-
if (typeof opts === 'string') opts = {key: opts}
18-
if (typeof opts === 'function') return store.createWriteStream(null, opts)
19-
20-
var bufferStream = new stream.PassThrough()
21-
22-
node.block.put(bufferStream, function (err, data) {
23-
if (err) return cb(err)
24-
25-
cb(null, {
26-
key: data.Key,
27-
size: data.Size
28-
})
29-
})
30-
31-
return bufferStream
32-
}
33-
34-
store.createReadStream = function (opts) {
35-
if (typeof opts === 'string') opts = {key: opts}
36-
var bufferStream = new stream.PassThrough()
37-
node.block.get(opts.key, function (err, stream) {
38-
if (err && !stream) return bufferStream.emit('error', 'No stream')
39-
stream.pipe(bufferStream)
40-
})
41-
42-
return bufferStream
14+
return {
15+
block: block(node),
16+
dag: dag(node),
17+
mfs: mfs(node)
4318
}
44-
45-
store.exists = function (opts, cb) {
46-
if (typeof opts === 'string') opts = {key: opts}
47-
var buf
48-
49-
try {
50-
buf = base58.decode(opts.key)
51-
void multihash.decode(buf)
52-
} catch (e) {
53-
return cb(null, false)
54-
}
55-
56-
node.block.get(opts.key, function (err, stream) {
57-
if (err) return cb(err)
58-
cb(null, true)
59-
})
60-
}
61-
62-
store.remove = function (opts, cb) {
63-
cb(null, false)
64-
}
65-
66-
return store
6719
}

lib/block.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
var stream = require('stream')
2+
var multihash = require('multihashes')
3+
var base58 = require('base58-native')
4+
5+
module.exports = function (node) {
6+
var store = {}
7+
8+
store.createWriteStream = function (opts, cb) {
9+
if (typeof opts === 'string') opts = {key: opts}
10+
if (typeof opts === 'function') return store.createWriteStream(null, opts)
11+
12+
var bufferStream = new stream.PassThrough()
13+
14+
node.block.put(bufferStream, function (err, data) {
15+
if (err) return cb(err)
16+
17+
cb(null, {
18+
key: data.Key,
19+
size: data.Size
20+
})
21+
})
22+
23+
return bufferStream
24+
}
25+
26+
store.createReadStream = function (opts) {
27+
if (typeof opts === 'string') opts = {key: opts}
28+
29+
var bufferStream = new stream.PassThrough()
30+
31+
node.block.get(opts.key, function (err, stream) {
32+
if (err && !stream) return bufferStream.emit('error', err)
33+
stream.pipe(bufferStream)
34+
})
35+
36+
return bufferStream
37+
}
38+
39+
store.exists = function (opts, cb) {
40+
if (typeof opts === 'string') opts = {key: opts}
41+
var buf
42+
43+
try {
44+
buf = base58.decode(opts.key)
45+
void multihash.decode(buf)
46+
} catch (e) {
47+
return cb(null, false)
48+
}
49+
50+
node.block.get(opts.key, function (err, stream) {
51+
if (err) return cb(err)
52+
cb(null, true)
53+
})
54+
}
55+
56+
store.remove = function (opts, cb) {
57+
cb(null, false)
58+
}
59+
60+
return store
61+
}

lib/dag.js

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
var stream = require('stream')
2+
var async = require('async')
3+
4+
var Node = function () {
5+
this.Links = []
6+
this.Data = new Buffer('')
7+
}
8+
9+
var Link = function () {
10+
this.Hash = ''
11+
this.Size = 0
12+
this.Name = ''
13+
}
14+
15+
module.exports = function (node) {
16+
var store = {}
17+
var root = new Node()
18+
var root_hash = ''
19+
var map = {}
20+
21+
store.createWriteStream = function (opts, cb) {
22+
if (typeof opts === 'string') opts = {key: opts}
23+
if (typeof opts === 'function') return store.createWriteStream(null, opts)
24+
if (typeof opts === 'undefined' || opts === null) opts = {}
25+
26+
var bufferStream = new stream.PassThrough()
27+
var buffer
28+
29+
bufferStream.on('data', function (chunk) {
30+
if (!buffer) buffer = chunk
31+
else {
32+
buffer = Buffer.concat([buffer, chunk], buffer.length + chunk.length)
33+
}
34+
})
35+
36+
bufferStream.on('end', function () {
37+
var blob = new Node()
38+
blob.Data = buffer.toString()
39+
async.waterfall([
40+
function (callback) {
41+
var raw = new Buffer(JSON.stringify(blob))
42+
node.object.put(raw, 'json', callback)
43+
},
44+
function (res, callback) {
45+
node.object.stat(res.Hash, function (err, stat) {
46+
callback(err, res, stat)
47+
})
48+
},
49+
function (res, stat, callback) {
50+
var link = new Link()
51+
52+
link.Hash = res.Hash
53+
link.Size = stat.CumulativeSize
54+
link.Name = opts.key || res.Hash
55+
56+
root.Links = root.Links.filter(function (item) {
57+
return item.Name !== opts.key
58+
})
59+
60+
root.Links.push(link)
61+
62+
root.Data = root_hash
63+
var raw = new Buffer(JSON.stringify(root))
64+
node.object.put(raw, 'json', function (err, new_root) {
65+
callback(err, link, new_root)
66+
})
67+
}, function (link, new_root, callback) {
68+
map[opts.key] = true
69+
70+
callback(null, {
71+
key: link.Name,
72+
root: new_root.Hash,
73+
hash: link.Hash,
74+
size: link.Size
75+
})
76+
77+
root_hash = new_root.Hash
78+
}
79+
], function (err, meta) {
80+
if (err) return cb(err)
81+
cb(null, meta)
82+
})
83+
})
84+
85+
return bufferStream
86+
}
87+
88+
store.createReadStream = function (opts) {
89+
if (typeof opts === 'string') {
90+
opts = {key: opts}
91+
}
92+
93+
var bufferStream = new stream.PassThrough()
94+
node.object.data((opts.root || root_hash) + '/' + opts.key, function (err, stream) {
95+
if (err && !stream) return bufferStream.emit('error', err)
96+
stream.pipe(bufferStream)
97+
})
98+
99+
return bufferStream
100+
}
101+
102+
store.exists = function (opts, cb) {
103+
if (typeof opts === 'string') {
104+
opts = {key: opts}
105+
}
106+
if (!root_hash) {
107+
return cb(null, false)
108+
}
109+
110+
node.object.stat((opts.root || root_hash) + '/' + opts.key, function (err, stat) {
111+
if (err) {
112+
cb(null, false)
113+
} else {
114+
cb(null, true)
115+
}
116+
})
117+
}
118+
119+
store.remove = function (opts, cb) {
120+
async.waterfall([
121+
function (callback) {
122+
root.Links = root.Links.filter(function (item) {
123+
return item.Name !== opts.key
124+
})
125+
126+
root.Data = root_hash
127+
var raw = new Buffer(JSON.stringify(root))
128+
node.object.put(raw, 'json', function (err, new_root) {
129+
callback(err, new_root)
130+
})
131+
},
132+
function (new_root, callback) {
133+
map[opts.key] = false
134+
135+
callback(null, true)
136+
137+
root_hash = new_root.Hash
138+
}
139+
], function (err, meta) {
140+
if (err) {
141+
return cb(err, false)
142+
}
143+
cb(null, meta)
144+
})
145+
}
146+
147+
return store
148+
}

0 commit comments

Comments
 (0)