UNPKG

tradestation-api-ts

Version:

A comprehensive TypeScript wrapper for TradeStation WebAPI v3

103 lines (102 loc) 3.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StreamManager = void 0; const events_1 = require("events"); class StreamManager { constructor(httpClient, config) { this.httpClient = httpClient; this.streams = new Map(); this.streamCount = 0; this.maxStreams = config.maxConcurrentStreams || 10; } async createStream(endpoint, params = {}, options = {}) { if (this.streamCount >= this.maxStreams) { throw new Error(`Maximum number of concurrent streams (${this.maxStreams}) reached`); } const streamId = `${endpoint}:${JSON.stringify(params)}`; if (this.streams.has(streamId)) { return this.streams.get(streamId); } const emitter = new events_1.EventEmitter(); this.streams.set(streamId, emitter); this.streamCount++; try { const stream = await this.httpClient.createStream(endpoint, { ...options, params }); let buffer = ''; stream.on('data', (chunk) => { try { // Add the chunk to our buffer buffer += chunk.toString(); // Split the buffer into lines const lines = buffer.split('\n'); // Process all complete lines for (let i = 0; i < lines.length - 1; i++) { const line = lines[i].trim(); if (line) { try { const data = JSON.parse(line); emitter.emit('data', data); } catch (parseError) { console.debug('Failed to parse line:', line); } } } // Keep the last incomplete line in the buffer buffer = lines[lines.length - 1]; } catch (error) { emitter.emit('error', new Error('Failed to process stream data')); } }); stream.on('error', (error) => { emitter.emit('error', error); this.closeStream(streamId); }); stream.on('end', () => { // Process any remaining data in the buffer if (buffer.trim()) { try { const data = JSON.parse(buffer.trim()); emitter.emit('data', data); } catch (parseError) { console.debug('Failed to parse remaining buffer:', buffer); } } emitter.emit('end'); this.closeStream(streamId); }); emitter.on('close', () => { stream.destroy?.(); this.closeStream(streamId); }); return emitter; } catch (error) { this.closeStream(streamId); throw error; } } closeStream(streamId) { const emitter = this.streams.get(streamId); if (emitter) { emitter.removeAllListeners(); this.streams.delete(streamId); this.streamCount--; } } closeAllStreams() { Array.from(this.streams.entries()).forEach(([streamId, emitter]) => { emitter.emit('close'); this.closeStream(streamId); }); } getActiveStreams() { return Array.from(this.streams.keys()); } } exports.StreamManager = StreamManager;