import * as plugins from './plugins.js'; import * as types from './types.js'; /** * Modern Response class that provides a fetch-like API */ export class SmartResponse implements types.ICoreResponse { private incomingMessage: plugins.http.IncomingMessage; private bodyBufferPromise: Promise | null = null; private consumed = false; // Public properties public readonly ok: boolean; public readonly status: number; public readonly statusText: string; public readonly headers: plugins.http.IncomingHttpHeaders; public readonly url: string; constructor(incomingMessage: plugins.http.IncomingMessage, url: string) { this.incomingMessage = incomingMessage; this.url = url; this.status = incomingMessage.statusCode || 0; this.statusText = incomingMessage.statusMessage || ''; this.ok = this.status >= 200 && this.status < 300; this.headers = incomingMessage.headers; } /** * Ensures the body can only be consumed once */ private ensureNotConsumed(): void { if (this.consumed) { throw new Error('Body has already been consumed'); } this.consumed = true; } /** * Collects the body as a buffer */ private async collectBody(): Promise { this.ensureNotConsumed(); if (this.bodyBufferPromise) { return this.bodyBufferPromise; } this.bodyBufferPromise = new Promise((resolve, reject) => { const chunks: Buffer[] = []; this.incomingMessage.on('data', (chunk: Buffer) => { chunks.push(chunk); }); this.incomingMessage.on('end', () => { resolve(Buffer.concat(chunks)); }); this.incomingMessage.on('error', reject); }); return this.bodyBufferPromise; } /** * Parse response as JSON */ async json(): Promise { const buffer = await this.collectBody(); const text = buffer.toString('utf-8'); try { return JSON.parse(text); } catch (error) { throw new Error(`Failed to parse JSON: ${error.message}`); } } /** * Get response as text */ async text(): Promise { const buffer = await this.collectBody(); return buffer.toString('utf-8'); } /** * Get response as ArrayBuffer */ async arrayBuffer(): Promise { const buffer = await this.collectBody(); return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); } /** * Get response as a readable stream */ stream(): NodeJS.ReadableStream { this.ensureNotConsumed(); return this.incomingMessage; } /** * Get the raw IncomingMessage (for legacy compatibility) */ raw(): plugins.http.IncomingMessage { return this.incomingMessage; } }