Skip to content

Commit

Permalink
feat: can start own ipfs node now mfs is in js-ipfs
Browse files Browse the repository at this point in the history
fixes #15
  • Loading branch information
achingbrain committed Aug 9, 2018
1 parent b855bd2 commit 05de260
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 48 deletions.
72 changes: 56 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,75 @@ npm install ipfs-blob-store

## Usage

`ipfs-blob-store` today requires a running [IPFS daemon](https://github.com/ipfs/go-ipfs/) to talk to over HTTP. This module will be able to be entirely self-contained once [js-ipfs](https://github.com/ipfs/js-ipfs) is complete.

`ipfs-blob-store` uses the [IPFS Files API](#) to create the abstraction of a mutable filesystem over snapshots of Merkle DAGs (per mutation). You'll need to use the Files API directly to get the `/ipfs/Qm...` address of the filesystem root so that other IPFS nodes can retrieve it.

It requires an IPFS node to run - you can either specify a host/port combination to connect to a remote daemon, pass an instance of [`ipfs`](https://www.npmjs.com/package/ipfs) or nothing at all to have the blob store manage it's own IPFS node.

### Self-managed IPFS node

```JavaScript
const ipfsBlobStore = require('ipfs-blob-store')

const store = await ipfsBlobStore()

store.exists('/my-file.txt', (error, exists) => {
// ...
})
```

### Pre-configured IPFS node

```JavaScript
const ipfsBlobStore = require('ipfs-blob-store')
const IPFS = require('ipfs')

const node = new IPFS({
// some config here
})

node.once('ready', () => {
const store = await ipfsBlobStore({
ipfs: node
})

store.exists('/my-file.txt', (error, exists) => {
// ...
})
})
```

### Remote IPFS daemon

```JavaScript
var ipfsBlobStore = require('ipfs-blob-store')
const ipfsBlobStore = require('ipfs-blob-store')

const store = await ipfsBlobStore({
host: '127.0.0.1',
port: 5001
})

store.exists('/my-file.txt', (error, exists) => {
// ...
})
```

### Options

```JavaScript
var options = {
ipfs: null, // an instance of ipfs or ipfs-api
port: 5001, // default value
host: '127.0.0.1', // default value
baseDir: '/', // default value
flush: true // default value
}

var store = ipfsBlobStore(options)

var ws = store.createWriteStream({
key: 'some/path/file.txt'
})
const store = await ipfsBlobStore(options)
```

ws.write('hello world\n')
ws.end(function() {
var rs = store.createReadStream({
key: 'some/path/file.txt'
})
### API

rs.pipe(process.stdout)
})
```
See [abstract-blob-store](https://www.npmjs.com/package/abstract-blob-store) for the blob store API.

## Contribute

Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ipfs-blob-store",
"version": "1.2.0",
"description": "An abstract-blob-store compatible implementation built using IPFS as the storage backend",
"main": "src/index.js",
"main": "src/create.js",
"scripts": {
"test": "node tests/blob-store-test.js",
"lint": "aegir lint"
Expand Down Expand Up @@ -32,8 +32,6 @@
"devDependencies": {
"abstract-blob-store": "^3.3.2",
"aegir": "^15.0.0",
"go-ipfs-dep": "~0.4.13",
"ipfsd-ctl": "~0.39.0",
"pre-commit": "^1.2.2",
"tape": "^4.8.0"
},
Expand All @@ -43,6 +41,8 @@
],
"dependencies": {
"debug": "^3.1.0",
"ipfs-api": "^23.0.0"
"ipfs": "~0.31.4",
"ipfs-api": "^23.0.0",
"promisify-es6": "^1.0.3"
}
}
53 changes: 53 additions & 0 deletions src/create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict'

const promisify = require('promisify-es6')
const IPFS = require('ipfs')
const remote = require('ipfs-api')
const mfs = require('./mfs')
const log = require('debug')('ipfs:blob-store:create')
const defaultOptions = {
ipfs: null,
flush: true,
baseDir: '/'
}

module.exports = promisify((opts, callback) => {
if (typeof opts === 'function') {
callback = opts
opts = defaultOptions
}

const options = Object.assign({}, defaultOptions, opts)

if (options.ipfs) {
log('Using pre-configured IPFS instance')
return setImmediate(() => callback(null, mfs(options)))
}

if (options.host && options.port) {
log(`Connecting to remote IPFS at ${options.host}:${options.port}`)
options.ipfs = remote(options.host, options.port)

return setImmediate(() => callback(null, mfs(options)))
}

log(`Starting an IPFS instance`)
callback = once(callback)

options.ipfs = new IPFS()
options.ipfs.once('ready', () => callback(null, mfs(options)))
options.ipfs.once('error', (error) => callback(error))
})

function once (cb) {
let called = false

return function () {
if (called) {
return
}

called = true
cb.apply(null, arguments)
}
}
16 changes: 0 additions & 16 deletions src/index.js

This file was deleted.

12 changes: 6 additions & 6 deletions src/mfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ module.exports = function (options) {
store.baseDir += '/'
}

var ipfsCtl = options.ipfsCtl
store.ipfsCtl = ipfsCtl
var ipfs = options.ipfs
store.ipfs = ipfs
if (typeof options.flush === 'boolean' && options.flush === false) {
// let it as it is
} else {
Expand All @@ -34,7 +34,7 @@ module.exports = function (options) {
size += buffer.length
})

ipfsCtl.files.write(writePath, bufferStream, {
ipfs.files.write(writePath, bufferStream, {
create: true,
parents: true,
flush: options.flush
Expand All @@ -60,7 +60,7 @@ module.exports = function (options) {
const readPath = normalisePath(store.baseDir + opts.key)

log(`read ${readPath}`)
const readableStream = ipfsCtl.files.readReadableStream(readPath)
const readableStream = ipfs.files.readReadableStream(readPath)

readableStream.on('error', (error) => {
if (error.toString().indexOf('does not exist') > -1 || error.toString().indexOf('Not a directory') > -1) {
Expand All @@ -79,7 +79,7 @@ module.exports = function (options) {
const statPath = normalisePath(store.baseDir + opts.key)

log(`stat ${statPath}`)
ipfsCtl.files.stat(statPath, {}, (err) => {
ipfs.files.stat(statPath, {}, (err) => {
if (err) {
if (err.code === 0) {
return cb(null, false)
Expand All @@ -100,7 +100,7 @@ module.exports = function (options) {
const rmPath = normalisePath(store.baseDir + opts.key)

log(`rm ${rmPath}`)
ipfsCtl.files.rm(rmPath, cb)
ipfs.files.rm(rmPath, cb)
}

return store
Expand Down
13 changes: 7 additions & 6 deletions tests/blob-store-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const test = require('tape')
const abstractBlobTests = require('abstract-blob-store/tests')
const ipfsBlobStore = require('../src')
const ipfsBlobStore = require('../')
const DaemonFactory = require('ipfsd-ctl')
const df = DaemonFactory.create()

Expand All @@ -21,22 +21,23 @@ df.spawn({
})

var common = {
setup: function (t, cb) {
setup: async function (t, cb) {
var options = {
baseDir: '/tests/',
port: 13000
port: 13000,
host: '127.0.0.1'
}
var store = ipfsBlobStore(options)
var store = await ipfsBlobStore(options)

store.ipfsCtl.files.mkdir(options.baseDir, { p: true }, (err) => {
store.ipfs.files.mkdir(options.baseDir, { p: true }, (err) => {
if (err) {
return console.error(err)
}
cb(null, store)
})
},
teardown: function (t, store, blob, cb) {
store.ipfsCtl.files.rm(store.baseDir, { recursive: true }, (err) => {
store.ipfs.files.rm(store.baseDir, { recursive: true }, (err) => {
if (err) {
return cb(err)
}
Expand Down

0 comments on commit 05de260

Please sign in to comment.