Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

Files add interface #288

Merged
merged 8 commits into from
Jun 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
"main": "lib/index.js",
"jsnext:main": "src/index.js",
"dependencies": {
"bl": "^1.1.2",
"async": "^2.0.0-rc.5",
"babel-runtime": "^6.6.1",
"bl": "^1.1.2",
"bs58": "^3.0.0",
"detect-node": "^2.0.3",
"flatmap": "0.0.3",
"glob": "^7.0.3",
"ipfs-merkle-dag": "^0.6.0",
"isstream": "^0.1.2",
"multiaddr": "^2.0.0",
"multipart-stream": "^2.0.1",
"ndjson": "^1.4.3",
Expand All @@ -30,7 +32,7 @@
"aegir": "^3.2.0",
"chai": "^3.5.0",
"gulp": "^3.9.1",
"interface-ipfs-core": "^0.1.4",
"interface-ipfs-core": "^0.2.0",
"ipfsd-ctl": "^0.14.0",
"pre-commit": "^1.1.2",
"stream-equal": "^0.1.8",
Expand Down Expand Up @@ -90,4 +92,4 @@
"url": "https://github.com/ipfs/js-ipfs-api/issues"
},
"homepage": "https://github.com/ipfs/js-ipfs-api"
}
}
25 changes: 25 additions & 0 deletions src/add-to-dagnode-transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict'

const async = require('async')
const getDagNode = require('./get-dagnode')

// transform { Hash: '...' } objects into { path: 'string', node: DAGNode }
module.exports = function (err, res, send, done) {
if (err) {
return done(err)
}
async.map(res, function map (entry, next) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please try to avoid adding async

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

roger. Due to time constraints, can we make that a issue to hit later? It would be good to explain in one paragraph (or even one line -> "async is a huge dependency, makes our browser lib fat") so that @noffle and other contribs try to avoid it in the future?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure there is already an issue on js-ipfs for exactly that

getDagNode(send, entry.Hash, function (err, node) {
if (err) {
return next(err)
}
var obj = {
path: entry.Name,
node: node
}
next(null, obj)
})
}, function (err, res) {
done(err, res)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could have been just passed done directly

})
}
20 changes: 20 additions & 0 deletions src/api/add-files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict'

const addToDagNodesTransform = require('../add-to-dagnode-transform')

module.exports = (send) => {
return function add (path, opts, cb) {
if (typeof (opts) === 'function' && cb === undefined) {
cb = opts
opts = {}
}

if (typeof (path) !== 'string') {
return cb(new Error('"path" must be a string'))
}

var sendWithTransform = send.withTransform(addToDagNodesTransform)

return sendWithTransform('add', null, opts, path, cb)
}
}
25 changes: 25 additions & 0 deletions src/api/add-url.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict'

const Wreck = require('wreck')
const addToDagNodesTransform = require('../add-to-dagnode-transform')

module.exports = (send) => {
return function add (url, opts, cb) {
if (typeof (opts) === 'function' && cb === undefined) {
cb = opts
opts = {}
}

if (typeof url !== 'string' || !url.startsWith('http')) {
return cb(new Error('"url" param must be an http(s) url'))
}

var sendWithTransform = send.withTransform(addToDagNodesTransform)

Wreck.request('GET', url, null, (err, res) => {
if (err) return cb(err)

sendWithTransform('add', null, opts, res, cb)
})
}
}
17 changes: 10 additions & 7 deletions src/api/add.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict'

const Wreck = require('wreck')
const isStream = require('isstream')
const addToDagNodesTransform = require('../add-to-dagnode-transform')

module.exports = (send) => {
return function add (files, opts, cb) {
Expand All @@ -9,14 +10,16 @@ module.exports = (send) => {
opts = {}
}

if (typeof files === 'string' && files.startsWith('http')) {
return Wreck.request('GET', files, null, (err, res) => {
if (err) return cb(err)
const good = Buffer.isBuffer(files) ||
isStream.isReadable(files) ||
Array.isArray(files)

send('add', null, opts, res, cb)
})
if (!good) {
return cb(new Error('"files" must be a buffer, readable stream, or array of objects'))
}

return send('add', null, opts, files, cb)
var sendWithTransform = send.withTransform(addToDagNodesTransform)

return sendWithTransform('add', null, opts, files, cb)
}
}
38 changes: 38 additions & 0 deletions src/get-dagnode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict'

const DAGNode = require('ipfs-merkle-dag').DAGNode
const bl = require('bl')
const async = require('async')

module.exports = function (send, hash, cb) {
// Retrieve the object and its data in parallel, then produce a DAGNode
// instance using this information.
async.parallel([
function get (done) {
send('object/get', hash, null, null, done)
},

function data (done) {
// WORKAROUND: request the object's data separately, since raw bits in JSON
// are interpreted as UTF-8 and corrupt the data.
// See https://github.com/ipfs/go-ipfs/issues/1582 for more details.
send('object/data', hash, null, null, done)
}],

function done (err, res) {
if (err) {
return cb(err)
}

var object = res[0]
var stream = res[1]

stream.pipe(bl(function (err, data) {
if (err) {
return cb(err)
}

cb(err, new DAGNode(data, object.Links))
}))
})
}
22 changes: 19 additions & 3 deletions src/load-commands.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
'use strict'

function requireCommands () {
return {
add: require('./api/add'),
var cmds = {
bitswap: require('./api/bitswap'),
block: require('./api/block'),
cat: require('./api/cat'),
Expand All @@ -11,7 +10,6 @@ function requireCommands () {
dht: require('./api/dht'),
diag: require('./api/diag'),
id: require('./api/id'),
files: require('./api/files'),
log: require('./api/log'),
ls: require('./api/ls'),
mount: require('./api/mount'),
Expand All @@ -24,6 +22,24 @@ function requireCommands () {
update: require('./api/update'),
version: require('./api/version')
}

// TODO: crowding the 'files' namespace temporarily for interface-ipfs-core
// compatibility, until 'files vs mfs' naming decision is resolved.
cmds.files = function (send) {
const files = require('./api/files')(send)
files.add = require('./api/add')(send)
return files
}

cmds.util = function (send) {
const util = {
addFiles: require('./api/add-files')(send),
addUrl: require('./api/add-url')(send)
}
return util
}

return cmds
}

function loadCommands (send) {
Expand Down
39 changes: 38 additions & 1 deletion src/request-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function requestAPI (config, path, args, qs, files, buffer, cb) {
// -- Interface

exports = module.exports = function getRequestAPI (config) {
return function (path, args, qs, files, buffer, cb) {
var send = function (path, args, qs, files, buffer, cb) {
if (typeof buffer === 'function') {
cb = buffer
buffer = false
Expand All @@ -127,4 +127,41 @@ exports = module.exports = function getRequestAPI (config) {

return requestAPI(config, path, args, qs, files, buffer, cb)
}

// Wraps the 'send' function such that an asynchronous transform may be
// applied to its result before passing it on to either its callback or
// promise.
send.withTransform = function (transform) {
return function (path, args, qs, files, buffer, cb) {
if (typeof buffer === 'function') {
cb = buffer
buffer = false
}

var p = send(path, args, qs, files, buffer, wrap(cb))

if (p instanceof Promise) {
return p.then((res) => {
return new Promise(function (resolve, reject) {
transform(null, res, send, function (err, res) {
if (err) reject(err)
else resolve(res)
})
})
})
} else {
return p
}

function wrap (done) {
if (done) {
return function (err, res) {
transform(err, res, send, done)
}
}
}
}
}

return send
}
Loading