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

Commit b0f367d

Browse files
authored
fix: handle node readable streams properly (#3890)
Readable streams returned from `fs.createReadStream` have a `.path` property which was throwing off the content normalisation. Fixes #3882
1 parent be4a542 commit b0f367d

File tree

5 files changed

+48
-5
lines changed

5 files changed

+48
-5
lines changed

packages/ipfs-core-utils/src/files/normalise-content.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@ import {
1414
/**
1515
* @param {import('./normalise').ToContent} input
1616
*/
17-
export async function * normaliseContent (input) {
17+
export async function normaliseContent (input) {
18+
return toAsyncGenerator(input)
19+
}
20+
21+
/**
22+
* @param {import('./normalise').ToContent} input
23+
*/
24+
async function * toAsyncGenerator (input) {
1825
// Bytes | String
1926
if (isBytes(input)) {
2027
yield toBytes(input)

packages/ipfs-core-utils/src/files/normalise.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222

2323
/**
2424
* @param {ImportCandidate | ImportCandidateStream} input
25-
* @param {(content:ToContent) => AsyncIterable<Uint8Array>} normaliseContent
25+
* @param {(content:ToContent) => Promise<AsyncIterable<Uint8Array>>} normaliseContent
2626
*/
2727
// eslint-disable-next-line complexity
2828
export async function * normalise (input, normaliseContent) {
@@ -72,6 +72,13 @@ export async function * normalise (input, normaliseContent) {
7272
return
7373
}
7474

75+
// fs.ReadStream<Bytes>
76+
if (value._readableState) {
77+
// @ts-ignore Node readable streams have a `.path` property so we need to pass it as the content
78+
yield * map(peekable, (/** @type {ImportCandidate} */ value) => toFileObject({ content: value }, normaliseContent))
79+
return
80+
}
81+
7582
// (Async)Iterable<Blob>
7683
// (Async)Iterable<String>
7784
// (Async)Iterable<{ path, content }>
@@ -103,7 +110,7 @@ export async function * normalise (input, normaliseContent) {
103110

104111
/**
105112
* @param {ImportCandidate} input
106-
* @param {(content:ToContent) => AsyncIterable<Uint8Array>} normaliseContent
113+
* @param {(content:ToContent) => Promise<AsyncIterable<Uint8Array>>} normaliseContent
107114
*/
108115
async function toFileObject (input, normaliseContent) {
109116
// @ts-ignore - Those properties don't exist on most input types
@@ -117,7 +124,6 @@ async function toFileObject (input, normaliseContent) {
117124
}
118125

119126
if (content) {
120-
// @ts-ignore TODO vmx 2021-03-30 enable again
121127
file.content = await normaliseContent(content)
122128
} else if (!path) { // Not already a file object with path or content prop
123129
// @ts-ignore - input still can be different ToContent

packages/ipfs-core-utils/test/files/normalise-input.spec.js

+29
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
66
import all from 'it-all'
77
import { File } from '@web-std/file'
88
import { normaliseInput } from '../../src/files/normalise-input.js'
9+
import { isNode } from 'ipfs-utils/src/env.js'
10+
import resolve from 'aegir/utils/resolve.js'
911

1012
const { Blob, ReadableStream } = globalThis
1113

@@ -208,4 +210,31 @@ describe('normalise-input', function () {
208210
describe('TypedArray', () => {
209211
testInputType(TYPEDARRAY, 'TypedArray', true)
210212
})
213+
214+
if (isNode) {
215+
/** @type {import('fs')} */
216+
let fs
217+
218+
before(async () => {
219+
fs = await import('fs')
220+
})
221+
222+
describe('Node fs.ReadStream', () => {
223+
const NODEFSREADSTREAM = () => {
224+
const path = resolve('test/fixtures/file.txt', 'ipfs-core-utils')
225+
226+
return fs.createReadStream(path)
227+
}
228+
229+
testInputType(NODEFSREADSTREAM, 'Node fs.ReadStream', false)
230+
231+
it('Iterable<Node fs.ReadStream>', async function () {
232+
await testContent(iterableOf(NODEFSREADSTREAM()))
233+
})
234+
235+
it('AsyncIterable<Node fs.ReadStream>', async function () {
236+
await testContent(asyncIterableOf(NODEFSREADSTREAM()))
237+
})
238+
})
239+
}
211240
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello world

packages/ipfs-grpc-client/src/core-api/files/write.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
* @param {*} content
1313
*/
1414
async function * stream (path, content) {
15-
for await (const buf of normaliseContent(content)) {
15+
for await (const buf of await normaliseContent(content)) {
1616
yield { path, content: buf }
1717
}
1818
}

0 commit comments

Comments
 (0)