/**
 * Native Stream Implementation - Node.js
 *
 * Uses Node.js native stream module for maximum performance.
 * Provides Readable, Writable, Transform, Duplex, and PassThrough streams.
 */
import { Readable, Writable as NodeWritable, Transform, Duplex, PassThrough, pipeline as nodePipeline, finished as nodeFinished } from "stream";
import { BufferedStream, BufferChunk, StringChunk } from "./buffered-stream.js";
import { PullStream } from "./pull-stream.js";
import { isAsyncIterable, isReadableStream, isTransformStream, isWritableStream } from "./internal/type-guards.js";
/**
 * Unified Writable class - wraps Node.js Writable with browser-compatible API
 *
 * Supports the same `{ stream }` option as browser version for wrapping existing streams.
 */
export class Writable extends NodeWritable {
    constructor(options) {
        // If wrapping an existing stream, proxy to it
        if (options?.stream) {
            const underlying = options.stream;
            // Create a pass-through wrapper that proxies to the underlying stream
            super({
                highWaterMark: options?.highWaterMark,
                objectMode: options?.objectMode,
                write(chunk, encoding, callback) {
                    underlying.write(chunk, encoding, callback);
                },
                final(callback) {
                    underlying.end(callback);
                }
            });
            // Proxy events from underlying stream, but ensure we clean up listeners so
            // the underlying stream cannot retain this wrapper longer than necessary.
            const onUnderlyingError = (err) => {
                this.emit("error", err);
            };
            const onUnderlyingClose = () => {
                this.emit("close");
            };
            const cleanup = () => {
                underlying.off("error", onUnderlyingError);
                underlying.off("close", onUnderlyingClose);
            };
            underlying.on("error", onUnderlyingError);
            underlying.on("close", onUnderlyingClose);
            this.once("close", cleanup);
            this.once("finish", cleanup);
        }
        else {
            super({
                highWaterMark: options?.highWaterMark,
                objectMode: options?.objectMode,
                write: options?.write,
                final: options?.final
            });
        }
    }
}
// =============================================================================
// Re-export native classes with our interfaces
// =============================================================================
export { Readable, Transform, Duplex, PassThrough };
// Standalone cross-platform helpers
export { PullStream, BufferedStream, StringChunk, BufferChunk };
// =============================================================================
// Cross-environment stream normalization
// =============================================================================
/**
 * Normalize a user-provided writable into a Node.js-compatible Writable.
 *
 * This keeps Web/Node branching at the stream-module boundary.
 */
export function normalizeWritable(stream) {
    if (stream instanceof Writable) {
        return stream;
    }
    // Node.js Writable: already compatible, avoid extra wrapper allocation.
    if (stream instanceof NodeWritable) {
        return stream;
    }
    // Web WritableStream: detect by getWriter() (avoid relying on global WritableStream).
    if (stream?.getWriter) {
        return NodeWritable.fromWeb(stream);
    }
    // Assume it structurally matches Node's Writable.
    return stream;
}
// Import for internal use
import { textDecoder } from "./shared.js";
const isPipelineOptions = (value) => {
    if (!value || typeof value !== "object") {
        return false;
    }
    // Avoid treating streams as options objects.
    if (typeof value.pipe === "function" ||
        typeof value.end === "function" ||
        typeof value.getReader === "function" ||
        typeof value.getWriter === "function") {
        return false;
    }
    return (Object.prototype.hasOwnProperty.call(value, "signal") ||
        Object.prototype.hasOwnProperty.call(value, "end"));
};
const toNodePipelineStream = (stream) => {
    // Node native streams (Readable/Transform/Duplex/Writable) are already compatible.
    if (stream instanceof Readable ||
        stream instanceof Transform ||
        stream instanceof Duplex ||
        stream instanceof NodeWritable) {
        return stream;
    }
    if (isTransformStream(stream)) {
        return Transform.fromWeb(stream);
    }
    if (isReadableStream(stream)) {
        return Readable.fromWeb(stream);
    }
    if (isWritableStream(stream)) {
        return NodeWritable.fromWeb(stream);
    }
    return stream;
};
/**
 * Pipeline streams together with proper error handling and cleanup.
 * Node.js compatible with support for options and callbacks.
 */
export function pipeline(...args) {
    let streams;
    let options;
    let callback;
    const lastArg = args[args.length - 1];
    if (typeof lastArg === "function") {
        callback = lastArg;
        streams = args.slice(0, -1);
    }
    else if (isPipelineOptions(lastArg)) {
        options = lastArg;
        streams = args.slice(0, -1);
    }
    else {
        streams = args;
    }
    const normalizedStreams = streams.map(toNodePipelineStream);
    const promise = new Promise((resolve, reject) => {
        const done = (err) => {
            if (err) {
                reject(err);
            }
            else {
                resolve();
            }
        };
        if (options) {
            nodePipeline(...normalizedStreams, options, done);
        }
        else {
            nodePipeline(...normalizedStreams, done);
        }
    });
    if (callback) {
        promise.then(() => callback()).catch(err => callback(err));
    }
    return promise;
}
/**
 * Wait for a stream to finish, close, or error.
 * Node.js compatible with support for options and callbacks.
 */
export function finished(stream, optionsOrCallback, callback) {
    let options;
    let cb;
    if (typeof optionsOrCallback === "function") {
        cb = optionsOrCallback;
    }
    else {
        options = optionsOrCallback;
        cb = callback;
    }
    const promise = new Promise((resolve, reject) => {
        const normalizedStream = toNodePipelineStream(stream);
        nodeFinished(normalizedStream, options, (err) => {
            // Node.js semantics: options.error defaults to true (report errors).
            // If options.error === false, ignore errors and resolve.
            if (err && options?.error !== false) {
                reject(err);
                return;
            }
            resolve();
        });
    });
    if (cb) {
        promise.then(() => cb()).catch(err => cb(err));
    }
    return promise;
}
// =============================================================================
// Stream Creation Functions
// =============================================================================
/**
 * Create a readable stream from various sources
 */
export function createReadable(options) {
    return new Readable({
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode,
        read: options?.read,
        destroy: options?.destroy
    });
}
/**
 * Create a readable stream from an async iterable
 */
export function createReadableFromAsyncIterable(iterable, options) {
    return Readable.from(iterable, {
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode ?? true
    });
}
/**
 * Create a readable stream from an array
 */
export function createReadableFromArray(data, options) {
    let index = 0;
    return new Readable({
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode ?? true,
        read() {
            if (index < data.length) {
                this.push(data[index++]);
            }
            else {
                this.push(null);
            }
        }
    });
}
/**
 * Create a writable stream
 */
export function createWritable(options) {
    return new Writable({
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode,
        write: options?.write,
        final: options?.final
    });
}
/**
 * Create a transform stream from a transform function
 */
export function createTransform(transformFn, options) {
    return new Transform({
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode,
        transform(chunk, encoding, callback) {
            try {
                const result = transformFn(chunk, encoding);
                if (result instanceof Promise) {
                    result
                        .then(data => {
                        if (data !== undefined) {
                            callback(null, data);
                        }
                        else {
                            callback();
                        }
                    })
                        .catch(callback);
                }
                else {
                    if (result !== undefined) {
                        callback(null, result);
                    }
                    else {
                        callback();
                    }
                }
            }
            catch (err) {
                callback(err);
            }
        },
        flush: options?.flush
            ? function (callback) {
                try {
                    const result = options.flush();
                    if (result instanceof Promise) {
                        result.then(data => callback(null, data)).catch(callback);
                    }
                    else if (result !== undefined) {
                        callback(null, result);
                    }
                    else {
                        callback();
                    }
                }
                catch (err) {
                    callback(err);
                }
            }
            : undefined
    });
}
/**
 * Create a duplex stream
 */
export function createDuplex(options) {
    return new Duplex({
        allowHalfOpen: options?.allowHalfOpen,
        readableHighWaterMark: options?.readableHighWaterMark,
        writableHighWaterMark: options?.writableHighWaterMark,
        readableObjectMode: options?.readableObjectMode,
        writableObjectMode: options?.writableObjectMode,
        read: options?.read,
        write: options?.write,
        final: options?.final,
        destroy: options?.destroy
    });
}
/**
 * Create a passthrough stream
 */
export function createPassThrough(options) {
    return new PassThrough({
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode
    });
}
// =============================================================================
// Collector Stream - Collects all chunks into an array
// =============================================================================
/**
 * A writable stream that collects all chunks
 */
export class Collector extends Writable {
    constructor(options) {
        super({
            highWaterMark: options?.highWaterMark,
            objectMode: options?.objectMode ?? true,
            write: ((chunk, _encoding, callback) => {
                this.chunks.push(chunk);
                callback();
            })
        });
        this.chunks = [];
    }
    /**
     * Get all collected data as a single Uint8Array (for binary mode)
     */
    toUint8Array() {
        const chunks = this.chunks;
        const len = chunks.length;
        if (len === 0) {
            return new Uint8Array(0);
        }
        if (len === 1) {
            const first = chunks[0];
            if (first instanceof Uint8Array) {
                return first;
            }
            if (Buffer.isBuffer(first)) {
                return new Uint8Array(first.buffer, first.byteOffset, first.byteLength);
            }
        }
        // Fast path: check first chunk type once
        const first = chunks[0];
        if (first instanceof Uint8Array || Buffer.isBuffer(first)) {
            // Calculate total length with simple loop (faster than reduce)
            let totalLength = 0;
            for (let i = 0; i < len; i++) {
                totalLength += chunks[i].length;
            }
            const result = new Uint8Array(totalLength);
            let offset = 0;
            for (let i = 0; i < len; i++) {
                const arr = chunks[i];
                result.set(arr, offset);
                offset += arr.length;
            }
            return result;
        }
        throw new Error("Collector contains non-binary data");
    }
    /**
     * Get all collected data as a string
     */
    toString() {
        const chunks = this.chunks;
        const len = chunks.length;
        if (len === 0) {
            return "";
        }
        const first = chunks[0];
        if (typeof first === "string") {
            // Fast path for string chunks
            if (len === 1) {
                return first;
            }
            return chunks.join("");
        }
        // Binary data - decode to string
        return textDecoder.decode(this.toUint8Array());
    }
}
/**
 * Create a collector stream
 */
export function createCollector(options) {
    return new Collector(options);
}
// =============================================================================
// Pull Stream - Read data on demand with pattern matching
// =============================================================================
/**
 * Create a pull stream
 */
export function createPullStream(options) {
    return new PullStream(options);
}
// =============================================================================
// Buffered Stream - Efficient chunk management
// =============================================================================
/**
 * Create a buffered stream
 */
export function createBufferedStream(options) {
    return new BufferedStream(options);
}
// =============================================================================
// Utility Functions
// =============================================================================
/**
 * Convert a stream to a promise that resolves when finished
 */
export async function streamToPromise(stream) {
    return finished(stream);
}
/**
 * Collect all data from a readable stream into a Uint8Array
 * (Node.js equivalent of browser streamToBuffer)
 */
export async function streamToBuffer(stream) {
    let iterable;
    if (isReadableStream(stream)) {
        iterable = Readable.fromWeb(stream);
    }
    else if (isAsyncIterable(stream)) {
        iterable = stream;
    }
    else {
        throw new Error("streamToBuffer: unsupported stream type");
    }
    const chunks = [];
    let totalLength = 0;
    for await (const chunk of iterable) {
        const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
        chunks.push(buf);
        totalLength += buf.length;
    }
    if (chunks.length === 0) {
        return new Uint8Array(0);
    }
    if (chunks.length === 1) {
        const b = chunks[0];
        return new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
    }
    // Use pre-calculated length for faster concat
    const buffer = Buffer.concat(chunks, totalLength);
    return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
}
/**
 * Collect all data from a readable stream into a Uint8Array
 */
export async function streamToUint8Array(stream) {
    return streamToBuffer(stream);
}
/**
 * Collect all data from a readable stream into a string
 */
export async function streamToString(stream, encoding) {
    const bytes = await streamToUint8Array(stream);
    return Buffer.from(bytes).toString((encoding ?? "utf8"));
}
/**
 * Drain a stream (consume all data without processing)
 */
export async function drainStream(stream) {
    let iterable;
    if (isReadableStream(stream)) {
        iterable = Readable.fromWeb(stream);
    }
    else if (isAsyncIterable(stream)) {
        iterable = stream;
    }
    else {
        throw new Error("drainStream: unsupported stream type");
    }
    for await (const _chunk of iterable) {
        // Consume data
    }
}
/**
 * Copy from a readable stream to a writable stream
 */
export async function copyStream(source, destination) {
    return pipeline(source, destination);
}
// =============================================================================
// Additional Utility Functions
// =============================================================================
/**
 * Add abort signal handling to any stream
 */
export function addAbortSignal(signal, stream) {
    if (signal.aborted) {
        stream.destroy(new Error("Aborted"));
        return stream;
    }
    const cleanup = () => {
        signal.removeEventListener("abort", onAbort);
        stream.off?.("close", onDone);
        stream.off?.("end", onDone);
        stream.off?.("finish", onDone);
        stream.off?.("error", onError);
    };
    const onAbort = () => {
        cleanup();
        stream.destroy(new Error("Aborted"));
    };
    const onDone = () => {
        cleanup();
    };
    const onError = () => {
        cleanup();
    };
    signal.addEventListener("abort", onAbort, { once: true });
    stream.once?.("close", onDone);
    stream.once?.("end", onDone);
    stream.once?.("finish", onDone);
    stream.once?.("error", onError);
    return stream;
}
/**
 * Create a readable stream from a generator function
 */
export function createReadableFromGenerator(generator, options) {
    return Readable.from(generator(), {
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode ?? true
    });
}
/**
 * Create a readable stream from a Promise
 */
export function createReadableFromPromise(promise, options) {
    const readable = new Readable({
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode ?? true,
        read() { }
    });
    promise
        .then(value => {
        readable.push(value);
        readable.push(null);
    })
        .catch(err => {
        readable.destroy(err);
    });
    return readable;
}
/**
 * Compose multiple transform streams into one
 */
export function compose(...transforms) {
    const len = transforms.length;
    if (len === 0) {
        return new PassThrough();
    }
    const isNativeTransform = (stream) => stream instanceof Transform;
    if (len === 1 && isNativeTransform(transforms[0])) {
        return transforms[0];
    }
    // Chain all transforms together once.
    for (let i = 0; i < len - 1; i++) {
        transforms[i].pipe(transforms[i + 1]);
    }
    const first = transforms[0];
    const last = transforms[len - 1];
    // Use a private output stream so we don't have to monkey-patch `write()` on the
    // public composed stream (which would break piping into it).
    const output = new PassThrough({ objectMode: last.readableObjectMode ?? true });
    last.pipe(output);
    let outputEnded = false;
    const pumpOutput = (target) => {
        if (outputEnded) {
            return;
        }
        while (true) {
            const chunk = output.read();
            if (chunk === null) {
                break;
            }
            if (!target.push(chunk)) {
                break;
            }
        }
    };
    const composed = new Transform({
        readableObjectMode: last.readableObjectMode,
        writableObjectMode: first.writableObjectMode,
        transform(chunk, encoding, callback) {
            try {
                // Forward writes into the head of the chain.
                first.write(chunk, encoding, callback);
            }
            catch (err) {
                callback(err);
            }
        },
        flush(callback) {
            // End the head of the chain; readable completion is driven by `output` ending.
            const onFinish = () => {
                cleanupFlush();
                callback();
            };
            const onError = (err) => {
                cleanupFlush();
                callback(err);
            };
            const cleanupFlush = () => {
                first.off?.("finish", onFinish);
                first.off?.("error", onError);
            };
            first.once?.("finish", onFinish);
            first.once?.("error", onError);
            first.end();
        },
        read() {
            pumpOutput(this);
        },
        destroy(err, callback) {
            try {
                output.destroy(err ?? undefined);
                for (const t of transforms) {
                    t.destroy?.(err ?? undefined);
                }
            }
            finally {
                callback(err);
            }
        }
    });
    const onOutputReadable = () => {
        pumpOutput(composed);
    };
    const onOutputEnd = () => {
        cleanupListeners();
        outputEnded = true;
        composed.push(null);
    };
    const onAnyError = (err) => {
        cleanupListeners();
        composed.destroy(err);
    };
    const transformErrorListeners = [];
    const cleanupListeners = () => {
        output.off("readable", onOutputReadable);
        output.off("end", onOutputEnd);
        output.off("error", onAnyError);
        for (const { t, fn } of transformErrorListeners) {
            t.off?.("error", fn);
        }
        transformErrorListeners.length = 0;
    };
    output.on("readable", onOutputReadable);
    output.once("end", onOutputEnd);
    output.once("error", onAnyError);
    for (const t of transforms) {
        const tt = t;
        tt.once?.("error", onAnyError);
        transformErrorListeners.push({ t: tt, fn: onAnyError });
    }
    composed.once("close", () => {
        cleanupListeners();
    });
    return composed;
}
/**
 * Wait for multiple streams to finish
 */
export async function finishedAll(streams) {
    const len = streams.length;
    if (len === 0) {
        return;
    }
    if (len === 1) {
        await finished(streams[0]);
        return;
    }
    // Create promise array in-place without intermediate allocation
    const promises = new Array(len);
    for (let i = 0; i < len; i++) {
        promises[i] = finished(streams[i]);
    }
    await Promise.all(promises);
}
// Reusable empty read function
const emptyRead = function () {
    this.push(null);
};
/**
 * Create a readable stream that emits nothing and immediately ends
 */
export function createEmptyReadable(options) {
    return new Readable({
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode,
        read: emptyRead
    });
}
// Reusable null write function
const nullWrite = (_chunk, _encoding, callback) => {
    callback();
};
/**
 * Create a writable stream that discards all data (like /dev/null)
 */
export function createNullWritable(options) {
    return new Writable({
        highWaterMark: options?.highWaterMark,
        objectMode: options?.objectMode,
        write: nullWrite
    });
}
/**
 * Promisified version of once for events
 */
export function once(emitter, event, options) {
    return new Promise((resolve, reject) => {
        const cleanup = () => {
            emitter.off(event, onEvent);
            emitter.off("error", onError);
            if (options?.signal) {
                options.signal.removeEventListener("abort", onAbort);
            }
        };
        const onEvent = (...args) => {
            cleanup();
            resolve(args);
        };
        const onError = (err) => {
            cleanup();
            reject(err);
        };
        const onAbort = () => {
            cleanup();
            reject(new Error("Aborted"));
        };
        emitter.once(event, onEvent);
        emitter.once("error", onError);
        if (options?.signal) {
            if (options.signal.aborted) {
                onAbort();
                return;
            }
            options.signal.addEventListener("abort", onAbort, { once: true });
        }
    });
}
/**
 * Convert a callback-based operation to a promise
 */
export function promisify(fn) {
    return new Promise((resolve, reject) => {
        fn((error, result) => {
            if (error) {
                reject(error);
            }
            else {
                resolve(result);
            }
        });
    });
}
// =============================================================================
// Type Guards
// =============================================================================
/**
 * Check if an object is a readable stream
 */
export function isReadable(obj) {
    if (obj == null) {
        return false;
    }
    if (obj instanceof Readable) {
        return true;
    }
    const o = obj;
    return typeof o.read === "function" && typeof o.pipe === "function";
}
/**
 * Check if an object is a writable stream
 */
export function isWritable(obj) {
    if (obj == null) {
        return false;
    }
    if (obj instanceof Writable) {
        return true;
    }
    const o = obj;
    return typeof o.write === "function" && typeof o.end === "function";
}
/**
 * Check if an object is a transform stream
 */
export function isTransform(obj) {
    if (obj == null) {
        return false;
    }
    if (obj instanceof Transform) {
        return true;
    }
    const o = obj;
    return (typeof o.read === "function" &&
        typeof o.pipe === "function" &&
        typeof o.write === "function" &&
        typeof o._transform === "function");
}
/**
 * Check if an object is a duplex stream
 */
export function isDuplex(obj) {
    if (obj == null) {
        return false;
    }
    if (obj instanceof Duplex) {
        return true;
    }
    const o = obj;
    return (typeof o.read === "function" &&
        typeof o.pipe === "function" &&
        typeof o.write === "function" &&
        typeof o.end === "function");
}
/**
 * Check if an object is any kind of stream
 */
export function isStream(obj) {
    if (obj == null) {
        return false;
    }
    if (obj instanceof Readable || obj instanceof Writable) {
        return true;
    }
    const o = obj;
    return ((typeof o.read === "function" && typeof o.pipe === "function") ||
        (typeof o.write === "function" && typeof o.end === "function"));
}
// =============================================================================
// Stream State Inspection Functions
// =============================================================================
/**
 * Check if a stream has been destroyed
 */
export function isDestroyed(stream) {
    return !!stream?.destroyed;
}
/**
 * Check if a readable stream has been disturbed (read from)
 */
export function isDisturbed(stream) {
    if (stream?.locked !== undefined) {
        return !!stream.locked;
    }
    const s = stream;
    return !!(s?.readableDidRead ||
        s?._didRead ||
        s?.readableEnded ||
        s?.destroyed ||
        s?._ended ||
        s?._destroyed);
}
/**
 * Check if a stream has an error
 */
export function isErrored(stream) {
    return !!stream?.errored;
}
// =============================================================================
// Default High Water Mark Management
// =============================================================================
/**
 * Get the default high water mark for streams
 */
export function getDefaultHighWaterMark(objectMode) {
    // Default values from Node.js stream module
    return objectMode ? 16 : 16 * 1024;
}
/**
 * Set the default high water mark for streams
 * Note: This is a no-op in this implementation as we use fixed defaults
 */
export function setDefaultHighWaterMark(_objectMode, _value) {
    // No-op - Node.js internal state cannot be modified safely
}
// =============================================================================
// Duplex Pair
// =============================================================================
/**
 * Create a pair of connected Duplex streams
 */
export function duplexPair(options) {
    // Use PassThrough as the simplest implementation
    const objectMode = options?.readableObjectMode ?? options?.writableObjectMode ?? options?.objectMode ?? false;
    const highWaterMark = options?.readableHighWaterMark ?? options?.writableHighWaterMark ?? options?.highWaterMark;
    const nodeOpts = {
        objectMode,
        highWaterMark
    };
    const passthrough1 = new PassThrough(nodeOpts);
    const passthrough2 = new PassThrough(nodeOpts);
    const duplex1 = new Duplex({
        allowHalfOpen: options?.allowHalfOpen,
        readableHighWaterMark: options?.readableHighWaterMark ?? highWaterMark,
        writableHighWaterMark: options?.writableHighWaterMark ?? highWaterMark,
        readableObjectMode: options?.readableObjectMode ?? objectMode,
        writableObjectMode: options?.writableObjectMode ?? objectMode,
        read() {
            // Will be pushed from duplex2
        },
        write(chunk, encoding, callback) {
            passthrough1.write(chunk, encoding, callback);
        },
        final(callback) {
            passthrough1.end(callback);
        }
    });
    const duplex2 = new Duplex({
        allowHalfOpen: options?.allowHalfOpen,
        readableHighWaterMark: options?.readableHighWaterMark ?? highWaterMark,
        writableHighWaterMark: options?.writableHighWaterMark ?? highWaterMark,
        readableObjectMode: options?.readableObjectMode ?? objectMode,
        writableObjectMode: options?.writableObjectMode ?? objectMode,
        read() {
            // Will be pushed from duplex1
        },
        write(chunk, encoding, callback) {
            passthrough2.write(chunk, encoding, callback);
        },
        final(callback) {
            passthrough2.end(callback);
        }
    });
    // Connect them
    passthrough1.on("data", chunk => duplex2.push(chunk));
    passthrough1.on("end", () => duplex2.push(null));
    passthrough2.on("data", chunk => duplex1.push(chunk));
    passthrough2.on("end", () => duplex1.push(null));
    return [duplex1, duplex2];
}
// =============================================================================
// Stream Consumers (like stream/consumers in Node.js)
// =============================================================================
export const consumers = {
    async arrayBuffer(stream) {
        const bytes = await streamToUint8Array(stream);
        return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
    },
    async blob(stream, options) {
        const bytes = await streamToUint8Array(stream);
        return new Blob([bytes], options);
    },
    async buffer(stream) {
        return streamToUint8Array(stream);
    },
    async json(stream) {
        const text = await consumers.text(stream);
        return JSON.parse(text);
    },
    async text(stream, encoding) {
        return streamToString(stream, encoding);
    }
};
// =============================================================================
// Promises API (like stream/promises in Node.js)
// =============================================================================
export const promises = {
    pipeline,
    finished
};
