import * as plugins from './smartfile.plugins.js'; import * as fsStream from './fsstream.js'; import { Readable } from 'stream'; type StreamSource = () => Promise; /** * The StreamFile class represents a file as a stream. * It allows creating streams from a file path, a URL, or a buffer. */ export class StreamFile { // INSTANCE relativeFilePath?: string; private streamSource: StreamSource; private constructor(streamSource: StreamSource, relativeFilePath?: string) { this.streamSource = streamSource; this.relativeFilePath = relativeFilePath; } // STATIC public static async fromPath(filePath: string): Promise { const streamSource = () => Promise.resolve(fsStream.createReadStream(filePath)); return new StreamFile(streamSource, filePath); } public static async fromUrl(url: string): Promise { const streamSource = async () => plugins.smartrequest.getStream(url); // Replace with actual plugin method return new StreamFile(streamSource); } public static fromBuffer(buffer: Buffer, relativeFilePath?: string): StreamFile { const streamSource = () => { const stream = new Readable(); stream.push(buffer); stream.push(null); // End of stream return Promise.resolve(stream); }; return new StreamFile(streamSource, relativeFilePath); } // METHODS /** * Creates a new readable stream from the source. */ public async createReadStream(): Promise { return this.streamSource(); } /** * Writes the stream to the disk at the specified path. * @param filePathArg The file path where the stream should be written. */ public async writeToDisk(filePathArg: string): Promise { const readStream = await this.createReadStream(); const writeStream = fsStream.createWriteStream(filePathArg); return new Promise((resolve, reject) => { readStream.pipe(writeStream); readStream.on('error', reject); writeStream.on('error', reject); writeStream.on('finish', resolve); }); } public async writeToDir(dirPathArg: string) { const filePath = plugins.path.join(dirPathArg, this.relativeFilePath); return this.writeToDisk(filePath); } public async getContentAsBuffer() { const done = plugins.smartpromise.defer(); const readStream = await this.createReadStream(); const chunks: Buffer[] = []; readStream.on('data', (chunk) => chunks.push(Buffer.from(chunk))); readStream.on('error', done.reject); readStream.on('end', () => { const contentBuffer = Buffer.concat(chunks); done.resolve(contentBuffer); }); return done.promise; } public async getContentAsString(formatArg: 'utf8' | 'binary' = 'utf8') { const contentBuffer = await this.getContentAsBuffer(); return contentBuffer.toString(formatArg); } }