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

WIP: Modify response to add body in React Native and logging daemon requests #2874

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.DS_Store
.connect-deps-cache/
.connect-deps.json
prettier.config.js
Comment on lines +1 to +4
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any objections to these changes making it into the .gitignore?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@hugomrdias @achingbrain Thoughts? Thanks!


# Dependency tools
package-lock.json
yarn.lock
Expand Down
47 changes: 45 additions & 2 deletions packages/ipfs-http-client/src/add/form-data.browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@ const normaliseInput = require('ipfs-utils/src/files/normalise-input')
const mtimeToObject = require('../lib/mtime-to-object')

exports.toFormData = async input => {
console.log("toFormData browser");
const files = normaliseInput(input)
console.log({ files })
const formData = new FormData()

// console.log({ formData })
let i = 0

for await (const file of files) {
// TODO FormData.append doesnt have a 4th arg
console.log({ file })
const headers = {}

if (file.mtime !== undefined && file.mtime !== null) {
console.log("file.mtime !== undefined && file.mtime !== null")
const mtime = mtimeToObject(file.mtime)

if (mtime) {
Expand All @@ -23,26 +29,39 @@ exports.toFormData = async input => {
}

if (file.mode !== undefined && file.mode !== null) {
console.log("file.mode !== undefined && file.mode !== null")
headers.mode = file.mode.toString(8).padStart(4, '0')
}

if (file.content) {
console.log("file.content", 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) {
console.log("file.content chunk", chunk)
bufs.push(chunk)
}

const newBlob = new Blob(bufs, { type: 'application/octet-stream' });
console.log({ newBlob })

if (newBlob.data) {
const newBlobData = newBlob.data;
console.log("newBlob data", newBlobData);
}

const encodedUriComponent = encodeURIComponent(file.path);
formData.append(
`file-${i}`,
new Blob(bufs, { type: 'application/octet-stream' }),
encodeURIComponent(file.path)
newBlob,
encodedUriComponent
// {
// header: headers
// }
)

} else {
formData.append(
`dir-${i}`,
Expand All @@ -54,8 +73,32 @@ exports.toFormData = async input => {
)
}

const keyToGet = 'file-0'

if (formData.entries) {
const formDataEntries = formData.entries();
for(var pair of formDataEntries) {
console.log(pair[0]+ ', '+ pair[1]);
}
const field = formData.get(keyToGet)
console.log({ field })
}

if (formData.getParts) {
const formDataParts = formData.getParts();
console.log({ formDataParts })
const field = formDataParts.find(item => item.fieldName === keyToGet);
if (field) {
console.log({ field })
}
}

i++
}

// for (var p of formData.entries()) {
// console.log({ p })
// }

return formData
}
1 change: 1 addition & 0 deletions packages/ipfs-http-client/src/add/form-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const normaliseInput = require('ipfs-utils/src/files/normalise-input')
const mtimeToObject = require('../lib/mtime-to-object')

exports.toFormData = async input => {
console.log("toFormData regular NOT USED IN REACT NATIVE");
const files = normaliseInput(input)
const formData = new FormData()
let i = 0
Expand Down
14 changes: 13 additions & 1 deletion packages/ipfs-http-client/src/add/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
'use strict'

const CID = require('cids')

const merge = require('merge-options')
const { toFormData } = require('./form-data')
const toCamel = require('../lib/object-to-camel')
const configure = require('../lib/configure')


module.exports = configure((api) => {
return async function * add (input, options = {}) {
console.log("Add called");
console.log("Using monorepo version")
const progressFn = options.progress
options = merge(
options,
Expand All @@ -18,20 +22,28 @@ module.exports = configure((api) => {
}
)

const formData = await toFormData(input)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@hugomrdias @achingbrain Do you have any stylistic objections to building formData in a separate line like this?


console.log({ formData })

const res = await api.ndjson('add', {
method: 'POST',
searchParams: options,
body: await toFormData(input),
body: formData,
timeout: options.timeout,
signal: options.signal
})

for await (let file of res) {
console.log({ file });
file = toCamel(file)
console.log("toCamelifiedFile", file);

if (progressFn && file.bytes) {
console.log("progressFn && file.bytes");
progressFn(file.bytes)
} else {
console.log("else");
yield toCoreInterface(file)
}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/ipfs-http-client/src/dag/put.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const configure = require('../lib/configure')

module.exports = configure(api => {
return async (dagNode, options = {}) => {
console.log("dag.put called")
console.log("Using monorepo version")
if (options.cid && (options.format || options.hashAlg)) {
throw new Error('Failed to put DAG node. Provide either `cid` OR `format` and `hashAlg` options')
} else if ((options.format && !options.hashAlg) || (!options.format && options.hashAlg)) {
Expand Down
4 changes: 3 additions & 1 deletion packages/ipfs-http-client/src/files/read.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict'

const { Buffer } = require('buffer')
const toAsyncIterable = require('../lib/stream-to-async-iterable')
// TODO: Decide if we can remove `toIterable`
const toIterable = require('stream-to-it/source')
const configure = require('../lib/configure')

Expand All @@ -13,7 +15,7 @@ module.exports = configure(api => {
searchParams: options
})

for await (const chunk of toIterable(res.body)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@hugomrdias It's interesting that there are still some methods where this toIterable(res.body) pattern is still around.

for await (const chunk of toAsyncIterable(res)) {
yield Buffer.from(chunk)
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/ipfs-http-client/src/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const Tar = require('it-tar')
const { Buffer } = require('buffer')
const CID = require('cids')

const configure = require('./lib/configure')

module.exports = configure(api => {
Expand Down
27 changes: 27 additions & 0 deletions packages/ipfs-http-client/src/lib/stream-to-async-iterable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict'

const toAsyncIterableOriginal = require('stream-to-it/source')

// Note: Turned this into a helper that wraps `stream-to-it/source`
// to handle the body undefined case without requiring that other libs
// that consume that package such as `js-ipfs` and `js-ipfs-utils` modify
// how they use it

module.exports = function toAsyncIterable (res) {
const { body } = res

// An env where res.body getter for ReadableStream with getReader
// is not supported, for example in React Native
if (!body) {
if (res.arrayBuffer) {
return (async function * () {
const arrayBuffer = await res.arrayBuffer()
yield arrayBuffer
})()
} else {
throw new Error('Neither Response.body nor Response.arrayBuffer is defined')
}
}

return toAsyncIterableOriginal(body)
}
6 changes: 6 additions & 0 deletions packages/ipfs-http-client/src/pubsub/subscribe.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const bs58 = require('bs58')
const { Buffer } = require('buffer')
const log = require('debug')('ipfs-http-client:pubsub:subscribe')
const SubscriptionTracker = require('./subscription-tracker')

// TODO: Update streamToAsyncIterator with any chances in light of
// this feature branch
const { streamToAsyncIterator, ndjson } = require('../lib/core')
Comment on lines +8 to 10
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@hugomrdias Can you give a short description of the new approach with streamToAsyncIterator compared with toIterable? Thanks!

const configure = require('../lib/configure')

Expand Down Expand Up @@ -45,6 +48,9 @@ module.exports = configure((api, options) => {

clearTimeout(ffWorkaround)

// Note: It's interesting that subscribe
// keeps this ndjson(tranformation(res)) pattern although
// that's now long from other IPFS methods
readMessages(ndjson(streamToAsyncIterator(res)), {
Comment on lines +51 to 54
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@hugomrdias For parallelism, would it make sense to get rid of this ndjson(transformer(res)) pattern here too since it was removed for other IPFS methods in the ky removal PR?

onMessage: handler,
onEnd: () => subsTracker.unsubscribe(topic, handler),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* eslint-env mocha */
'use strict'

const { expect } = require('interface-ipfs-core/src/utils/mocha')
const toAsyncIterable = require('../src/lib/stream-to-async-iterable')

describe('lib/stream-to-async-iterable', () => {
it('should return input if already async iterable', () => {
const input = {
[Symbol.asyncIterator] () {
return this
}
}
const res = { body: input }
expect(toAsyncIterable(res)).to.equal(input)
})

it('should convert reader to async iterable', async () => {
const inputData = [2, 31, 3, 4]

const input = {
getReader () {
let i = 0
return {
read () {
return Promise.resolve(
i === inputData.length
? { done: true }
: { value: inputData[i++] }
)
},
releaseLock () { }
}
}
}
const res = { body: input }

const chunks = []
for await (const chunk of toAsyncIterable(res)) {
chunks.push(chunk)
}

expect(chunks).to.eql(inputData)
})

it('should return an async iterable even if res.body is undefined', async () => {
const inputData = [2]
const res = {
arrayBuffer () {
return Promise.resolve(inputData[0])
}
}

const chunks = []
for await (const chunk of toAsyncIterable(res)) {
chunks.push(chunk)
}

expect(chunks).to.eql(inputData)
})

it('should throw if res.body and res.arrayBuffer are undefined', () => {
const res = {}
expect(() => toAsyncIterable(res)).to.throw('Neither Response.body nor Response.arrayBuffer is defined')
})

it('should throw on unknown stream', () => {
const res = { body: {} }
expect(() => toAsyncIterable(res)).to.throw('unknown stream')
})
})
Loading