UNPKG

@yoyo-org/progressive-json

Version:

Stream and render JSON data as it arrives - perfect for AI responses, large datasets, and real-time updates

111 lines (110 loc) 3.88 kB
/** * HTTP adapter for Axios instances * Allows using pre-configured Axios instances with Progressive JSON */ export class AxiosAdapter { constructor(axiosInstance) { this.axiosInstance = axiosInstance; } async stream(url, options = {}) { const response = await this.request(url, options); return response.stream; } async request(url, options = {}) { try { const config = { method: options.method || 'GET', url, headers: options.headers, timeout: options.timeout, responseType: 'stream', // Critical: we need the stream signal: options.signal, }; // Add body/data if provided if (options.body) { config.data = options.body; } const response = await this.axiosInstance.request(config); // Convert the Node.js stream to Web Stream (for browser compatibility) const stream = this.convertToWebStream(response.data); return { stream, status: response.status, statusText: response.statusText, headers: response.headers, ok: response.status >= 200 && response.status < 300, }; } catch (error) { // Handle Axios errors if (error.response) { throw new Error(`HTTP Error: ${error.response.status} ${error.response.statusText}`); } else if (error.request) { throw new Error('Network Error: No response received'); } else { throw new Error(`Request Error: ${error.message}`); } } } /** * Convert Node.js readable stream or browser stream to Web ReadableStream<Uint8Array> */ convertToWebStream(data) { // If it's already a ReadableStream, return it if (data instanceof ReadableStream) { return data; } // If it's a Node.js readable stream (server-side) if (data && typeof data.on === 'function' && typeof data.read === 'function') { return new ReadableStream({ start(controller) { data.on('data', (chunk) => { controller.enqueue(new Uint8Array(chunk)); }); data.on('end', () => { controller.close(); }); data.on('error', (error) => { controller.error(error); }); }, cancel() { if (typeof data.destroy === 'function') { data.destroy(); } } }); } // If it's a string (fallback) if (typeof data === 'string') { const encoder = new TextEncoder(); const bytes = encoder.encode(data); return new ReadableStream({ start(controller) { controller.enqueue(bytes); controller.close(); } }); } // If it's already Uint8Array if (data instanceof Uint8Array) { return new ReadableStream({ start(controller) { controller.enqueue(data); controller.close(); } }); } throw new Error('Unsupported response data type for streaming'); } } /** * Factory function to create an Axios adapter * @param axiosInstance - Your pre-configured Axios instance * @returns AxiosAdapter instance */ export function createAxiosAdapter(axiosInstance) { return new AxiosAdapter(axiosInstance); }