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

Commit 4103dc6

Browse files
author
Alan Shaw
committed
refactor: convert addFromFs
License: MIT Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
1 parent 620ed72 commit 4103dc6

File tree

7 files changed

+119
-55
lines changed

7 files changed

+119
-55
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"fs": false,
2020
"stream": "readable-stream",
2121
"ky-universal": "ky/umd",
22-
"./src/add/form-data.js": "./src/add/form-data.browser.js"
22+
"./src/add/form-data.js": "./src/add/form-data.browser.js",
23+
"./src/add-from-fs/index.js": "./src/add-from-fs/index.browser.js"
2324
},
2425
"repository": "github:ipfs/js-ipfs-http-client",
2526
"scripts": {
@@ -61,6 +62,7 @@
6162
"is-stream": "^2.0.0",
6263
"iso-stream-http": "~0.1.2",
6364
"iso-url": "~0.4.6",
65+
"it-pushable": "^1.2.1",
6466
"it-to-stream": "^0.1.1",
6567
"iterable-ndjson": "^1.1.0",
6668
"just-kebab-case": "^1.1.0",

src/add-from-fs/glob-source.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
'use strict'
2+
3+
const Fs = require('fs')
4+
const Path = require('path')
5+
const glob = require('glob')
6+
const pushable = require('it-pushable')
7+
const errCode = require('err-code')
8+
9+
/**
10+
* Create an AsyncIterable that can be passed to ipfs.add for the
11+
* provided file paths.
12+
*
13+
* @param {String} ...paths File system path(s) to glob from
14+
* @param {Object} [options] Optional options
15+
* @param {Boolean} [options.recursive] Recursively glob all paths in directories
16+
* @param {Boolean} [options.hidden] Include .dot files in matched paths
17+
* @param {Array<String>} [options.ignore] Glob paths to ignore
18+
* @param {Boolean} [options.followSymlinks] follow symlinks
19+
* @returns {AsyncIterable}
20+
*/
21+
module.exports = (...args) => (async function * () {
22+
const options = typeof args[args.length - 1] === 'string' ? {} : args.pop()
23+
const paths = args
24+
25+
const globSourceOptions = {
26+
recursive: options.recursive,
27+
glob: {
28+
dot: Boolean(options.hidden),
29+
ignore: Array.isArray(options.ignore) ? options.ignore : [],
30+
follow: options.followSymlinks != null ? options.followSymlinks : true
31+
}
32+
}
33+
34+
// Check the input paths comply with options.recursive and convert to glob sources
35+
const results = await Promise.all(paths.map(pathAndType))
36+
const globSources = results.map(r => toGlobSource(r, globSourceOptions))
37+
38+
for (const globSource of globSources) {
39+
for await (const { path, contentPath } of globSource) {
40+
yield { path, content: Fs.createReadStream(contentPath) }
41+
}
42+
}
43+
})()
44+
45+
function toGlobSource ({ path, type }, options) {
46+
return (async function * () {
47+
options = options || {}
48+
49+
const baseName = Path.basename(path)
50+
51+
if (type === 'file') {
52+
yield { path: baseName, contentPath: path }
53+
return
54+
}
55+
56+
if (type === 'dir' && !options.recursive) {
57+
throw errCode(
58+
new Error(`'${path}' is a directory and recursive option not set`),
59+
'ERR_DIR_NON_RECURSIVE',
60+
{ path }
61+
)
62+
}
63+
64+
const globOptions = Object.assign({}, options.glob, {
65+
cwd: path,
66+
nodir: true,
67+
realpath: false,
68+
absolute: false
69+
})
70+
71+
// TODO: want to use pull-glob but it doesn't have the features...
72+
const pusher = pushable()
73+
74+
glob('**/*', globOptions)
75+
.on('match', m => pusher.push(m))
76+
.on('end', () => pusher.end())
77+
.on('abort', () => pusher.end())
78+
.on('error', err => pusher.end(err))
79+
80+
for await (const p of pusher) {
81+
yield {
82+
path: `${baseName}/${toPosix(p)}`,
83+
contentPath: Path.join(path, p)
84+
}
85+
}
86+
})()
87+
}
88+
89+
async function pathAndType (path) {
90+
const stat = await Fs.promises.stat(path)
91+
return { path, type: stat.isDirectory() ? 'dir' : 'file' }
92+
}
93+
94+
const toPosix = path => path.replace(/\\/g, '/')

src/add-from-fs/index.browser.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict'
2+
3+
module.exports = () => { throw new Error('unavailable in the browser') }

src/add-from-fs/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict'
2+
3+
const configure = require('../lib/configure')
4+
const globSource = require('./glob-source')
5+
6+
module.exports = configure(({ ky }) => {
7+
const add = require('../add')({ ky })
8+
return (path, options) => add(globSource(path, options), options)
9+
})

src/files-regular/add-from-fs.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/files-regular/add-readable-stream.js

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/utils/load-commands.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@ function requireCommands () {
2424
const add = require('../add')(config)
2525
return pullify.transform(add)
2626
},
27-
// TODO: convert
28-
addFromFs: require('../files-regular/add-from-fs'),
27+
addFromFs: (_, config) => {
28+
const addFromFs = collectify(require('../add-from-fs')(config))
29+
return (path, options, callback) => {
30+
if (typeof options === 'function') {
31+
callback = options
32+
options = {}
33+
}
34+
return nodeify(addFromFs(path, options), callback)
35+
}
36+
},
2937
addFromURL: (_, config) => {
3038
const addFromURL = collectify(require('../add-from-url')(config))
3139
return (url, options, callback) => {

0 commit comments

Comments
 (0)