This repository has been archived by the owner on Mar 10, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 299
refactor: fetch add #1063
Closed
Closed
refactor: fetch add #1063
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
6c17081
feat: enable pubsub in the browser
0974b73
fix: tests
0f3e640
fix: use included querystring module
850e1fb
chore: appease linter
4de1e09
chore: update interface-ipfs-core
2437cf4
chore: skip test
4a89c6a
fix: skip in the right place
b656aab
refactor: more readable code for consuming message stream
e6f97d3
fix: add workaround for subscribe in Firefox
d84716a
refactor: use promise-nodeify
684b2a1
test: add tests for lib fns
176556c
chore: appease linter
cea1bd5
fix: tests in browser
636d302
perf: use URLSearchParams in the browser
62529c3
chore: appease linter
b58c489
fix: oops, removed more code than I should have
70653ad
refactor: use ky
e600d98
fix: configure tests
29647db
chore: appease linter
f973a13
feat: add, addPullStream, addFromFs and addFromStream
625a6a2
refactor: use ky
c0ef769
refactor: convert addReadableStream
916efbd
refactor: convert addFromFs
c213336
refactor: remove unused code
9b302b8
fix: tests
8481fb6
fix: tests
cb5e2b0
fix: normalize input for iterable of buffer or blob
6192ef0
Merge branch 'master' into refactor/fetch-add
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
'use strict' | ||
|
||
const Fs = require('fs') | ||
const Path = require('path') | ||
const glob = require('glob') | ||
const pushable = require('it-pushable') | ||
const errCode = require('err-code') | ||
|
||
/** | ||
* Create an AsyncIterable that can be passed to ipfs.add for the | ||
* provided file paths. | ||
* | ||
* @param {String} ...paths File system path(s) to glob from | ||
* @param {Object} [options] Optional options | ||
* @param {Boolean} [options.recursive] Recursively glob all paths in directories | ||
* @param {Boolean} [options.hidden] Include .dot files in matched paths | ||
* @param {Array<String>} [options.ignore] Glob paths to ignore | ||
* @param {Boolean} [options.followSymlinks] follow symlinks | ||
* @returns {AsyncIterable} | ||
*/ | ||
module.exports = (...args) => (async function * () { | ||
const options = typeof args[args.length - 1] === 'string' ? {} : args.pop() | ||
const paths = args | ||
|
||
const globSourceOptions = { | ||
recursive: options.recursive, | ||
glob: { | ||
dot: Boolean(options.hidden), | ||
ignore: Array.isArray(options.ignore) ? options.ignore : [], | ||
follow: options.followSymlinks != null ? options.followSymlinks : true | ||
} | ||
} | ||
|
||
// Check the input paths comply with options.recursive and convert to glob sources | ||
const results = await Promise.all(paths.map(pathAndType)) | ||
const globSources = results.map(r => toGlobSource(r, globSourceOptions)) | ||
|
||
for (const globSource of globSources) { | ||
for await (const { path, contentPath } of globSource) { | ||
yield { path, content: Fs.createReadStream(contentPath) } | ||
} | ||
} | ||
})() | ||
|
||
function toGlobSource ({ path, type }, options) { | ||
return (async function * () { | ||
options = options || {} | ||
|
||
const baseName = Path.basename(path) | ||
|
||
if (type === 'file') { | ||
yield { path: baseName, contentPath: path } | ||
return | ||
} | ||
|
||
if (type === 'dir' && !options.recursive) { | ||
throw errCode( | ||
new Error(`'${path}' is a directory and recursive option not set`), | ||
'ERR_DIR_NON_RECURSIVE', | ||
{ path } | ||
) | ||
} | ||
|
||
const globOptions = Object.assign({}, options.glob, { | ||
cwd: path, | ||
nodir: true, | ||
realpath: false, | ||
absolute: false | ||
}) | ||
|
||
// TODO: want to use pull-glob but it doesn't have the features... | ||
const pusher = pushable() | ||
|
||
glob('**/*', globOptions) | ||
.on('match', m => pusher.push(m)) | ||
.on('end', () => pusher.end()) | ||
.on('abort', () => pusher.end()) | ||
.on('error', err => pusher.end(err)) | ||
|
||
for await (const p of pusher) { | ||
yield { | ||
path: `${baseName}/${toPosix(p)}`, | ||
contentPath: Path.join(path, p) | ||
} | ||
} | ||
})() | ||
} | ||
|
||
async function pathAndType (path) { | ||
const stat = await Fs.promises.stat(path) | ||
return { path, type: stat.isDirectory() ? 'dir' : 'file' } | ||
} | ||
|
||
const toPosix = path => path.replace(/\\/g, '/') | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
'use strict' | ||
|
||
module.exports = () => () => { throw new Error('unavailable in the browser') } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
'use strict' | ||
|
||
const configure = require('../lib/configure') | ||
const globSource = require('./glob-source') | ||
|
||
module.exports = configure(({ ky }) => { | ||
const add = require('../add')({ ky }) | ||
return (path, options) => add(globSource(path, options), options) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
'use strict' | ||
|
||
const kyDefault = require('ky-universal').default | ||
const configure = require('./lib/configure') | ||
const toIterable = require('./lib/stream-to-iterable') | ||
|
||
module.exports = configure(({ ky }) => { | ||
const add = require('./add')({ ky }) | ||
|
||
return (url, options) => (async function * () { | ||
options = options || {} | ||
|
||
const { body } = await kyDefault.get(url) | ||
|
||
const input = { | ||
path: decodeURIComponent(new URL(url).pathname.split('/').pop() || ''), | ||
content: toIterable(body) | ||
} | ||
|
||
for await (const file of add(input, options)) { | ||
yield file | ||
} | ||
})() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
'use strict' | ||
/* eslint-env browser */ | ||
|
||
const normaliseInput = require('./normalise-input') | ||
|
||
exports.toFormData = async (input) => { | ||
const files = normaliseInput(input) | ||
const formData = new FormData() | ||
let i = 0 | ||
|
||
for await (const file of files) { | ||
if (file.content) { | ||
// In the browser there's _currently_ no streaming upload, buffer up our | ||
// async iterator chunks and append a big Blob :( | ||
// One day, this will be browser streams | ||
const bufs = [] | ||
for await (const chunk of file.content) { | ||
bufs.push(Buffer.isBuffer(chunk) ? chunk.buffer : chunk) | ||
} | ||
|
||
formData.append(`file-${i}`, new Blob(bufs, { type: 'application/octet-stream' }), file.path) | ||
} else { | ||
formData.append(`dir-${i}`, new Blob([], { type: 'application/x-directory' }), file.path) | ||
} | ||
|
||
i++ | ||
} | ||
|
||
return formData | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
'use strict' | ||
|
||
const FormData = require('form-data') | ||
const { Buffer } = require('buffer') | ||
const toStream = require('it-to-stream') | ||
const normaliseInput = require('./normalise-input') | ||
|
||
exports.toFormData = async (input) => { | ||
const files = normaliseInput(input) | ||
const formData = new FormData() | ||
let i = 0 | ||
|
||
for await (const file of files) { | ||
if (file.content) { | ||
// In Node.js, FormData can be passed a stream so no need to buffer | ||
formData.append( | ||
`file-${i}`, | ||
// FIXME: add a `path` property to the stream so `form-data` doesn't set | ||
// a Content-Length header that is only the sum of the size of the | ||
// header/footer when knownLength option (below) is null. | ||
Object.assign( | ||
toStream.readable(file.content), | ||
{ path: file.path || `file-${i}` } | ||
), | ||
{ | ||
filepath: encodeURIComponent(file.path), | ||
contentType: 'application/octet-stream', | ||
knownLength: file.content.length // Send Content-Length header if known | ||
} | ||
) | ||
} else { | ||
formData.append(`dir-${i}`, Buffer.alloc(0), { | ||
filepath: encodeURIComponent(file.path), | ||
contentType: 'application/x-directory' | ||
}) | ||
} | ||
|
||
i++ | ||
} | ||
|
||
return formData | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
'use strict' | ||
|
||
const ndjson = require('iterable-ndjson') | ||
const configure = require('../lib/configure') | ||
const toIterable = require('../lib/stream-to-iterable') | ||
const { toFormData } = require('./form-data') | ||
const toCamel = require('../lib/object-to-camel') | ||
|
||
module.exports = configure(({ ky }) => { | ||
return (input, options) => (async function * () { | ||
options = options || {} | ||
|
||
const searchParams = new URLSearchParams(options.searchParams) | ||
|
||
searchParams.set('stream-channels', true) | ||
if (options.chunker) searchParams.set('chunker', options.chunker) | ||
if (options.cidVersion) searchParams.set('cid-version', options.cidVersion) | ||
if (options.cidBase) searchParams.set('cid-base', options.cidBase) | ||
if (options.enableShardingExperiment != null) searchParams.set('enable-sharding-experiment', options.enableShardingExperiment) | ||
if (options.hashAlg) searchParams.set('hash', options.hashAlg) | ||
if (options.onlyHash != null) searchParams.set('only-hash', options.onlyHash) | ||
if (options.pin != null) searchParams.set('pin', options.pin) | ||
if (options.progress) searchParams.set('progress', true) | ||
if (options.quiet != null) searchParams.set('quiet', options.quiet) | ||
if (options.quieter != null) searchParams.set('quieter', options.quieter) | ||
if (options.rawLeaves != null) searchParams.set('raw-leaves', options.rawLeaves) | ||
if (options.shardSplitThreshold) searchParams.set('shard-split-threshold', options.shardSplitThreshold) | ||
if (options.silent) searchParams.set('silent', options.silent) | ||
if (options.trickle != null) searchParams.set('trickle', options.trickle) | ||
if (options.wrapWithDirectory != null) searchParams.set('wrap-with-directory', options.wrapWithDirectory) | ||
|
||
const res = await ky.post('add', { | ||
timeout: options.timeout, | ||
signal: options.signal, | ||
headers: options.headers, | ||
searchParams, | ||
body: await toFormData(input) | ||
}) | ||
|
||
for await (let file of ndjson(toIterable(res.body))) { | ||
file = toCamel(file) | ||
// console.log(file) | ||
if (options.progress && file.bytes) { | ||
options.progress(file.bytes) | ||
} else { | ||
yield toCoreInterface(file) | ||
} | ||
} | ||
})() | ||
}) | ||
|
||
function toCoreInterface ({ name, hash, size }) { | ||
return { path: name, hash, size: parseInt(size) } | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: use https://github.com/achingbrain/it-glob instead