CRBT-Team/Purplet

View on GitHub
packages/utils/src/blob.ts

Summary

Maintainability
A
2 hrs
Test Coverage
interface ArrayBufferable {
  arrayBuffer(): Promise<ArrayBuffer>;
}

interface Streamable {
  stream(): ReadableStream<Uint8Array>;
}

export type BlobResolvable =
  | string
  | Uint8Array
  | Blob
  | ArrayBufferLike
  | ArrayBufferable
  | Streamable
  | Buffer
  | AsyncIterable<string | Uint8Array | Blob | ArrayBufferLike | Buffer>;

function isArrayBufferable(data: BlobResolvable): data is ArrayBufferable {
  return typeof (data as ArrayBufferable).arrayBuffer === 'function';
}

function isStreamable(data: BlobResolvable): data is Streamable {
  return typeof (data as Streamable).stream === 'function';
}

function isAsyncIterable(
  data: BlobResolvable
): data is AsyncIterable<string | Uint8Array | Blob | ArrayBufferLike | Buffer> {
  return typeof (data as AsyncIterable<BlobResolvable>)[Symbol.asyncIterator] === 'function';
}

export async function toBlob(data: BlobResolvable): Promise<Blob> {
  if (data instanceof Blob) {
    return data;
  }
  if (isArrayBufferable(data)) {
    return new Blob([await data.arrayBuffer()]);
  }
  if (isStreamable(data)) {
    const stream = data.stream().getReader();
    const values = [];

    let read;
    do {
      read = await stream.read();
      read.value && values.push(read.value);
    } while (!read.done);

    return new Blob(values);
  }
  if (isAsyncIterable(data)) {
    const values = [];

    for await (const value of data) {
      values.push(value);
    }

    return new Blob(values);
  }
  return new Blob([data]);
}