Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Add object endpoints and cli commands #85

Merged
merged 1 commit into from
Mar 14, 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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@
"webpack": "^2.0.7-beta"
},
"dependencies": {
"bl": "^1.0.0",
"bl": "^1.1.2",
"boom": "^3.1.1",
"bs58": "^3.0.0",
"debug": "^2.2.0",
"hapi": "^12.0.0",
"ipfs-api": "^2.13.1",
"ipfs-blocks": "^0.1.0",
"ipfs-merkle-dag": "^0.2.1",
"ipfs-multipart": "0.0.1",
"ipfs-multipart": "^0.1.0",
"ipfs-repo": "^0.5.0",
"joi": "^8.0.2",
"lodash.get": "^4.0.0",
Expand Down
41 changes: 41 additions & 0 deletions src/cli/commands/object/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict'

const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const debug = require('debug')
const log = debug('cli:object')
log.error = debug('cli:object:error')

module.exports = Command.extend({
desc: 'Outputs the raw bytes in an IPFS object',

options: {},

run: (key) => {
if (!key) {
throw new Error("Argument 'key' is required")
}

var ipfs = utils.getIPFS()

const mh = utils.isDaemonOn()
? key
: new Buffer(bs58.decode(key))

ipfs.object.data(mh, (err, data) => {
if (err) {
log.error(err)
throw err
}

if (data instanceof Buffer) {
console.log(data.toString())
return
Copy link
Member

Choose a reason for hiding this comment

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

what is this doing?

Copy link
Member Author

Choose a reason for hiding this comment

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

js-ipfs-api's object.data accepts multihashes as a string, core needs the Buffer instead.

js-ipfs-api returns a stream, core returns a Buffer

}

// js-ipfs-api output (http stream)
data.pipe(process.stdout)
})
}
})
50 changes: 50 additions & 0 deletions src/cli/commands/object/get.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict'

const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const debug = require('debug')
const log = debug('cli:object')
log.error = debug('cli:object:error')

module.exports = Command.extend({
desc: 'Get and serialize the DAG node named by <key>',

options: {},

run: (key) => {
if (!key) {
throw new Error("Argument 'key' is required")
}

var ipfs = utils.getIPFS()

if (utils.isDaemonOn()) {
return ipfs.object.get(key, (err, obj) => {
if (err) {
log.error(err)
throw err
}

console.log(JSON.stringify(obj))
Copy link
Member

Choose a reason for hiding this comment

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

does this print in the same way that go-ipfs does? I believe go-ipfs does some formatting rather then printing the obj directly

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes:
screen shot 2016-03-14 at 16 05 13
(last command was with a daemon running)

Copy link
Member

Choose a reason for hiding this comment

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

cool :)

})
}

const mh = new Buffer(bs58.decode(key))
ipfs.object.get(mh, (err, obj) => {
if (err) {
log.error(err)
throw err
}

console.log(JSON.stringify({
Links: obj.links.map((link) => ({
Name: link.name,
Hash: bs58.encode(link.hash).toString(),
Size: link.size
})),
Data: obj.data.toString()
Copy link
Member

Choose a reason for hiding this comment

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

which seems you do it here :)

Copy link
Member Author

Choose a reason for hiding this comment

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

That's because core returns an object with lowercase keys and the multihashes as a buffer, on the other hand the js-ipfs-api returns the http API response which returns the object like go-ipfs

}))
})
}
})
44 changes: 44 additions & 0 deletions src/cli/commands/object/links.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict'

const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const debug = require('debug')
const log = debug('cli:object')
log.error = debug('cli:object:error')

module.exports = Command.extend({
desc: 'Outputs the links pointed to by the specified object',

options: {},

run: (key) => {
if (!key) {
throw new Error("Argument 'key' is required")
Copy link
Member

Choose a reason for hiding this comment

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

can you do this before utils.getIPFS() ?

}

var ipfs = utils.getIPFS()

const mh = utils.isDaemonOn()
? key
: new Buffer(bs58.decode(key))

ipfs.object.links(mh, (err, links) => {
if (err) {
log.error(err)
throw err
}

if (links.Links) { // js-ipfs-api output
links.Links.forEach((link) => {
console.log(link.Hash, link.Size, link.Name)
})
return
}

links.forEach((link) => {
console.log(bs58.encode(link.hash).toString(), link.size, link.name)
})
})
}
})
32 changes: 32 additions & 0 deletions src/cli/commands/object/new.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict'

const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const debug = require('debug')
const log = debug('cli:object')
log.error = debug('cli:object:error')

module.exports = Command.extend({
desc: 'Create new ipfs objects',

options: {},

run: (template) => {
var ipfs = utils.getIPFS()

ipfs.object.new(template, (err, obj) => {
if (err) {
log.error(err)
throw err
}

if (typeof obj.Hash === 'string') { // js-ipfs-api output
console.log(obj.Hash)
return
}

console.log(bs58.encode(obj.Hash).toString())
})
}
})
76 changes: 76 additions & 0 deletions src/cli/commands/object/put.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
'use strict'

const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const bl = require('bl')
const fs = require('fs')
const mDAG = require('ipfs-merkle-dag')
const DAGNode = mDAG.DAGNode
const debug = require('debug')
const log = debug('cli:object')
log.error = debug('cli:object:error')

function parseJSONBuffer (buf) {
try {
const parsed = JSON.parse(buf.toString())
return {
data: new Buffer(parsed.Data),
links: parsed.Links ? parsed.Links.map((link) => ({
name: link.Name,
hash: new Buffer(bs58.decode(link.Hash)),
size: link.Size
})) : []
}
} catch (err) {
log.error(err)
throw new Error('failed to parse JSON: ' + err)
}
}

function parseAndAddNode (buf) {
var ipfs = utils.getIPFS()

if (utils.isDaemonOn()) {
return ipfs.object.put(buf, 'json', (err, obj) => {
if (err) {
log.error(err)
throw err
}

console.log('added', obj.Hash)
})
}

const parsed = parseJSONBuffer(buf)
const dagNode = new DAGNode(parsed.data, parsed.links)
ipfs.object.put(dagNode, (err, obj) => {
if (err) {
log.error(err)
throw err
}

console.log('added', bs58.encode(dagNode.multihash()).toString())
})
}

module.exports = Command.extend({
desc: 'Stores input as a DAG object, outputs its key',

options: {},

run: (filePath) => {
if (filePath) {
return parseAndAddNode(fs.readFileSync(filePath))
}

process.stdin.pipe(bl((err, input) => {
if (err) {
log.error(err)
throw err
}

parseAndAddNode(input)
}))
Copy link
Member

Choose a reason for hiding this comment

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

this whole command could be more simple. Also, seems like I can cat file | jsipfs object put and it would get confused

Copy link
Member Author

Choose a reason for hiding this comment

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

According to go-ipfs, you can:

➜  js-ipfs git:(feature/object) ipfs object put --help

    ipfs object put <data> - Stores input as a DAG object, outputs its key.

(...)

    Examples:

        $ echo '{ "Data": "abc" }' | ipfs object put

    This creates a node with the data 'abc' and no links. For an object with links,
    create a file named 'node.json' with the contents:

        {
            "Data": "another",
            "Links": [ {
                "Name": "some link",
                "Hash": "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V",
                "Size": 8
            } ]
        }

    And then run:

        $ ipfs object put node.json

Will try to simplify it though :)

Copy link
Member

Choose a reason for hiding this comment

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

got it. I meant that it doesn't seem the code to prevent something like

cat file | jsipfs object put <another object> 

Copy link
Member Author

Choose a reason for hiding this comment

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

go-ipfs doesn't prevent it either, if you pass a file path it simply takes priority over the stdin :)

}
})
39 changes: 39 additions & 0 deletions src/cli/commands/object/stat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict'

const Command = require('ronin').Command
const utils = require('../../utils')
const bs58 = require('bs58')
const debug = require('debug')
const log = debug('cli:object')
log.error = debug('cli:object:error')

module.exports = Command.extend({
desc: 'Get stats for the DAG node named by <key>',

options: {},

run: (key) => {
if (!key) {
throw new Error("Argument 'key' is required")
}

var ipfs = utils.getIPFS()

const mh = utils.isDaemonOn()
? key
: new Buffer(bs58.decode(key))

ipfs.object.stat(mh, (err, stats) => {
if (err) {
log.error(err)
throw err
}

delete stats.Hash // only for js-ipfs-api output

Object.keys(stats).forEach((key) => {
console.log(`${key}: ${stats[key]}`)
})
})
}
})
Loading