import { CompositeError } from '@chunkd/core';
import { Readable } from 'stream';
export async function toBuffer(stream) {
    return new Promise((resolve, reject) => {
        const buf = [];
        stream.on('data', (chunk) => buf.push(chunk));
        stream.on('end', () => resolve(Buffer.concat(buf)));
        stream.on('error', (err) => reject(`error converting stream - ${err}`));
    });
}
export function toReadable(r) {
    if (typeof r === 'string')
        r = Buffer.from(r);
    return Readable.from(r);
}
// TODO this should be provided by @chunkd/fs as it already provides a memory source
export class FsMemory {
    constructor() {
        this.protocol = 'memory';
        this.files = new Map();
    }
    async read(filePath) {
        const data = this.files.get(filePath);
        if (data == null)
            throw new CompositeError('Not found', 404, new Error());
        return data;
    }
    stream(filePath) {
        const buf = this.files.get(filePath);
        if (buf == null)
            throw new CompositeError('Not found', 404, new Error());
        return toReadable(buf);
    }
    async write(filePath, buffer) {
        if (typeof buffer === 'string') {
            this.files.set(filePath, Buffer.from(buffer));
            return;
        }
        if (Buffer.isBuffer(buffer)) {
            this.files.set(filePath, buffer);
            return;
        }
        const buf = await toBuffer(buffer);
        this.files.set(filePath, buf);
    }
    async *list(filePath) {
        for (const file of this.files.keys()) {
            if (file.startsWith(filePath))
                yield file;
        }
    }
    async *details(filePath) {
        for await (const file of this.list(filePath)) {
            const data = await this.head(file);
            if (data == null)
                continue;
            yield data;
        }
    }
    async exists(filePath) {
        const dat = await this.head(filePath);
        return dat != null;
    }
    async head(filePath) {
        const buf = this.files.get(filePath);
        if (buf == null)
            return null;
        return { path: filePath, size: buf.length };
    }
    source() {
        throw new Error('Method not implemented.');
    }
}
