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

Commit 95f99eb

Browse files
committed
feat: add mfs implementation
1 parent c1ee247 commit 95f99eb

File tree

26 files changed

+483
-191
lines changed

26 files changed

+483
-191
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ You can check the development status at the [Waffle Board](https://waffle.io/ipf
7474
- [Network](#network)
7575
- [Node Management](#node-management)
7676
- [Domain data types](#domain-data-types)
77+
- [Util](#util)
7778
- [FAQ](#faq)
7879
- [Running js-ipfs with Docker](#running-js-ipfs-with-docker)
7980
- [Packages](#packages)

examples/browser-script-tag/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ <h2>Some suggestions</h2>
3030
<code style="display:block; white-space:pre-wrap; background-color:#d7d6d6">
3131
node.files.add(new node.types.Buffer('Hello world!'), (err, filesAdded) => {
3232
if (err) {
33-
return console.error('Error - ipfs files add', err, res)
33+
return console.error('Error - ipfs add', err, res)
3434
}
3535

3636
filesAdded.forEach((file) => console.log('successfully stored', file.hash))

examples/circuit-relaying/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"ipfs-pubsub-room": "~0.3.0"
1919
},
2020
"devDependencies": {
21-
"aegir": "^13.0.5",
21+
"aegir": "^14.0.0",
2222
"http-server": "~0.10.0",
2323
"ipfs-css": "~0.2.0",
2424
"parcel-bundler": "^1.6.2",

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
"ipfs-block": "~0.7.1",
109109
"ipfs-block-service": "~0.14.0",
110110
"ipfs-http-response": "~0.1.2",
111+
"ipfs-mfs": "~0.0.14",
111112
"ipfs-multipart": "~0.1.0",
112113
"ipfs-repo": "~0.22.1",
113114
"ipfs-unixfs": "~0.1.15",
@@ -166,7 +167,8 @@
166167
"through2": "^2.0.3",
167168
"update-notifier": "^2.5.0",
168169
"yargs": "^12.0.1",
169-
"yargs-parser": "^10.1.0"
170+
"yargs-parser": "^10.1.0",
171+
"yargs-promise": "^1.1.0"
170172
},
171173
"optionalDependencies": {
172174
"prom-client": "^11.1.1",

src/cli/bin.js

+53-34
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
'use strict'
44

5+
const YargsPromise = require('yargs-promise')
56
const yargs = require('yargs')
67
const updateNotifier = require('update-notifier')
78
const readPkgUp = require('read-pkg-up')
8-
const fs = require('fs')
9-
const path = require('path')
109
const utils = require('./utils')
1110
const print = utils.print
11+
const mfs = require('ipfs-mfs/cli')
12+
const debug = require('debug')('ipfs:cli')
1213

1314
const pkg = readPkgUp.sync({cwd: __dirname}).pkg
1415
updateNotifier({
@@ -18,10 +19,6 @@ updateNotifier({
1819

1920
const args = process.argv.slice(2)
2021

21-
// Determine if the first argument is a sub-system command
22-
const commandNames = fs.readdirSync(path.join(__dirname, 'commands'))
23-
const isCommand = commandNames.includes(`${args[0]}.js`)
24-
2522
const cli = yargs
2623
.option('silent', {
2724
desc: 'Write no output',
@@ -34,14 +31,6 @@ const cli = yargs
3431
type: 'string',
3532
default: ''
3633
})
37-
.commandDir('commands', {
38-
// Only include the commands for the sub-system we're using, or include all
39-
// if no sub-system command has been passed.
40-
include (path, filename) {
41-
if (!isCommand) return true
42-
return `${args[0]}.js` === filename
43-
}
44-
})
4534
.epilog(utils.ipfsPathHelp)
4635
.demandCommand(1)
4736
.fail((msg, err, yargs) => {
@@ -56,27 +45,15 @@ const cli = yargs
5645
yargs.showHelp()
5746
})
5847

59-
// If not a sub-system command then load the top level aliases
60-
if (!isCommand) {
61-
// NOTE: This creates an alias of
62-
// `jsipfs files {add, get, cat}` to `jsipfs {add, get, cat}`.
63-
// This will stay until https://github.com./ipfs/specs/issues/98 is resolved.
64-
const addCmd = require('./commands/files/add')
65-
const catCmd = require('./commands/files/cat')
66-
const getCmd = require('./commands/files/get')
67-
const aliases = [addCmd, catCmd, getCmd]
68-
aliases.forEach((alias) => {
69-
cli.command(alias.command, alias.describe, alias.builder, alias.handler)
70-
})
71-
}
72-
7348
// Need to skip to avoid locking as these commands
7449
// don't require a daemon
7550
if (args[0] === 'daemon' || args[0] === 'init') {
7651
cli
7752
.help()
7853
.strict()
7954
.completion()
55+
.command(require('./commands/daemon'))
56+
.command(require('./commands/init'))
8057
.parse(args)
8158
} else {
8259
// here we have to make a separate yargs instance with
@@ -86,19 +63,61 @@ if (args[0] === 'daemon' || args[0] === 'init') {
8663
if (err) {
8764
throw err
8865
}
66+
8967
utils.getIPFS(argv, (err, ipfs, cleanup) => {
90-
if (err) { throw err }
68+
if (err) {
69+
throw err
70+
}
71+
72+
// add mfs commands
73+
mfs(cli)
74+
75+
// NOTE: This creates an alias of
76+
// `jsipfs files {add, get, cat}` to `jsipfs {add, get, cat}`.
77+
// This will stay until https://github.com./ipfs/specs/issues/98 is resolved.
78+
const addCmd = require('./commands/files/add')
79+
const catCmd = require('./commands/files/cat')
80+
const getCmd = require('./commands/files/get')
81+
const aliases = [addCmd, catCmd, getCmd]
82+
aliases.forEach((alias) => {
83+
cli.command(alias)
84+
})
9185

9286
cli
87+
.commandDir('commands')
9388
.help()
9489
.strict()
9590
.completion()
96-
.parse(args, { ipfs: ipfs }, (err, argv, output) => {
97-
if (output) { print(output) }
9891

99-
cleanup(() => {
100-
if (err) { throw err }
101-
})
92+
let exitCode = 0
93+
94+
const parser = new YargsPromise(cli, { ipfs })
95+
parser.parse(args)
96+
.then(({ data, argv }) => {
97+
if (data) {
98+
print(data)
99+
}
100+
})
101+
.catch((arg) => {
102+
debug(arg)
103+
104+
// the argument can have a different shape depending on where the error came from
105+
if (arg.message) {
106+
print(arg.message)
107+
} else if (arg.error && arg.error.message) {
108+
print(arg.error.message)
109+
} else {
110+
print('Unknown error, please re-run the command with DEBUG=ipfs:cli to see debug output')
111+
}
112+
113+
exitCode = 1
114+
})
115+
.then(() => cleanup())
116+
.catch(() => {})
117+
.then(() => {
118+
if (exitCode !== 0) {
119+
process.exit(exitCode)
120+
}
102121
})
103122
})
104123
})

src/cli/commands/files.js

-20
This file was deleted.

src/cli/commands/files/get.js

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ function fileHandler (dir) {
3030
callback(err)
3131
} else {
3232
const fullFilePath = path.join(dir, file.path)
33+
3334
if (file.content) {
3435
file.content
3536
.pipe(fs.createWriteStream(fullFilePath))

src/cli/utils.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const log = debug('cli')
99
log.error = debug('cli:error')
1010
const Progress = require('progress')
1111
const byteman = require('byteman')
12+
const promisify = require('promisify-es6')
1213

1314
exports = module.exports
1415

@@ -40,7 +41,7 @@ function getAPICtl (apiAddr) {
4041

4142
exports.getIPFS = (argv, callback) => {
4243
if (argv.api || isDaemonOn()) {
43-
return callback(null, getAPICtl(argv.api), (cb) => cb())
44+
return callback(null, getAPICtl(argv.api), promisify((cb) => cb()))
4445
}
4546

4647
// Required inline to reduce startup time
@@ -55,13 +56,13 @@ exports.getIPFS = (argv, callback) => {
5556
}
5657
})
5758

58-
const cleanup = (cb) => {
59+
const cleanup = promisify((cb) => {
5960
if (node && node._repo && !node._repo.closed) {
60-
node._repo.close(() => cb())
61+
node._repo.close((err) => cb(err))
6162
} else {
6263
cb()
6364
}
64-
}
65+
})
6566

6667
node.on('error', (err) => {
6768
throw err

src/core/components/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ exports.dht = require('./dht')
2626
exports.dns = require('./dns')
2727
exports.key = require('./key')
2828
exports.stats = require('./stats')
29+
exports.mfs = require('ipfs-mfs/core')

src/core/config.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const schema = Joi.object().keys({
77
Joi.object(), // TODO: schema for IPFS repo
88
Joi.string()
99
).allow(null),
10+
repoOwner: Joi.boolean().default(true),
1011
init: Joi.alternatives().try(
1112
Joi.boolean(),
1213
Joi.object().keys({ bits: Joi.number().integer() })

src/core/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ class IPFS extends EventEmitter {
133133
isIPFS: isIPFS
134134
}
135135

136+
// ipfs.files
137+
const mfs = components.mfs(this, this._options)
138+
139+
Object.keys(mfs).forEach(key => {
140+
this.files[key] = mfs[key]
141+
})
142+
136143
boot(this)
137144
}
138145
}

src/http/api/resources/files.js

+12-7
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ exports.parseKey = (request, reply) => {
3434
if (!request.query.arg) {
3535
return reply({
3636
Message: "Argument 'key' is required",
37-
Code: 0
37+
Code: 0,
38+
Type: 'error'
3839
}).code(400).takeover()
3940
}
4041

@@ -54,7 +55,8 @@ exports.parseKey = (request, reply) => {
5455
log.error(err)
5556
return reply({
5657
Message: 'invalid ipfs ref path',
57-
Code: 0
58+
Code: 0,
59+
Type: 'error'
5860
}).code(500).takeover()
5961
}
6062

@@ -81,9 +83,9 @@ exports.cat = {
8183
if (err) {
8284
log.error(err)
8385
if (err.message === 'No such file') {
84-
reply({Message: 'No such file'}).code(500)
86+
reply({Message: 'No such file', Code: 0, Type: 'error'}).code(500)
8587
} else {
86-
reply({Message: 'Failed to cat file: ' + err, Code: 0}).code(500)
88+
reply({Message: 'Failed to cat file: ' + err, Code: 0, Type: 'error'}).code(500)
8789
}
8890
return
8991
}
@@ -177,7 +179,8 @@ exports.add = {
177179
if (!request.payload) {
178180
return reply({
179181
Message: 'Array, Buffer, or String is required.',
180-
code: 0
182+
Code: 0,
183+
Type: 'error'
181184
}).code(400).takeover()
182185
}
183186

@@ -211,7 +214,8 @@ exports.add = {
211214
if (!filesParsed) {
212215
return reply({
213216
Message: "File argument 'data' is required.",
214-
code: 0
217+
Code: 0,
218+
Type: 'error'
215219
}).code(400).takeover()
216220
}
217221
fileAdder.end()
@@ -302,7 +306,8 @@ exports.immutableLs = {
302306
if (err) {
303307
return reply({
304308
Message: 'Failed to list dir: ' + err.message,
305-
Code: 0
309+
Code: 0,
310+
Type: 'error'
306311
}).code(500).takeover()
307312
}
308313

src/http/api/routes/files.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22

33
const resources = require('./../resources')
4+
const mfs = require('ipfs-mfs/http')
45

56
module.exports = (server) => {
67
const api = server.select('API')
@@ -54,4 +55,6 @@ module.exports = (server) => {
5455
handler: resources.files.immutableLs.handler
5556
}
5657
})
58+
59+
mfs(api)
5760
}

src/http/error-handler.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,15 @@ module.exports = (api, server) => {
1414

1515
let statusCode = 200
1616
let msg = 'Sorry, something went wrong, please retrace your steps.'
17+
let code = 1
1718

1819
if (res.isBoom) {
1920
statusCode = res.output.payload.statusCode
21+
msg = res.output.payload.message
22+
23+
if (res.data && res.data.code !== undefined) {
24+
code = res.data.code
25+
}
2026

2127
if (res.message && res.isDeveloperError) {
2228
msg = res.message.replace('Uncaught error: ', '')
@@ -36,7 +42,8 @@ module.exports = (api, server) => {
3642

3743
reply({
3844
Message: msg,
39-
Code: 1
45+
Code: code,
46+
Type: 'error'
4047
}).code(statusCode)
4148
return
4249
}

0 commit comments

Comments
 (0)