import { InvalidParametersError } from '@libp2p/interface' import blobToIt from 'blob-to-it' import browserStreamToIt from 'browser-readablestream-to-it' import all from 'it-all' import map from 'it-map' import itPeekable from 'it-peekable' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { isBytes, isReadableStream, isBlob } from './utils.ts' import type { ToContent } from '../../index.ts' async function * toAsyncIterable (thing: T): AsyncIterable { yield thing } export async function normaliseContent (input: ToContent): Promise> { // Bytes | String if (isBytes(input)) { return toAsyncIterable(toBytes(input)) } if (typeof input === 'string' || input instanceof String) { return toAsyncIterable(toBytes(input.toString())) } // Blob if (isBlob(input)) { return blobToIt(input) } // Browser stream if (isReadableStream(input)) { input = browserStreamToIt(input) } // (Async)Iterator if (Symbol.iterator in input || Symbol.asyncIterator in input) { // @ts-expect-error cannot detect iterability const peekable = itPeekable(input) // eslint-disable-next-line @typescript-eslint/await-thenable const { value, done } = await peekable.peek() if (done === true) { // make sure empty iterators result in empty files return toAsyncIterable(new Uint8Array(0)) } peekable.push(value) // (Async)Iterable if (Number.isInteger(value)) { // eslint-disable-next-line @typescript-eslint/await-thenable return toAsyncIterable(Uint8Array.from(await all(peekable))) } // (Async)Iterable if (isBytes(value) || typeof value === 'string' || value instanceof String) { // @ts-expect-error cannot derive type return map(peekable, toBytes) } } throw new InvalidParametersError(`Unexpected input: ${input}`) } function toBytes (chunk: ArrayBuffer | ArrayBufferView | string | InstanceType | number[]): Uint8Array { if (chunk instanceof Uint8Array) { return chunk } if (ArrayBuffer.isView(chunk)) { return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength) } if (chunk instanceof ArrayBuffer) { return new Uint8Array(chunk) } if (Array.isArray(chunk)) { return Uint8Array.from(chunk) } return uint8ArrayFromString(chunk.toString()) }