UNPKG

@devgrid/netron

Version:

A powerful TypeScript library for building distributed systems with event bus, streaming capabilities, and remote object invocation. Features WebSocket-based bidirectional communication between Node.js and browser environments, service discovery, and type

118 lines 4.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NetronWritableStream = void 0; const stream_1 = require("stream"); const uid_1 = require("./uid"); const packet_1 = require("./packet"); const uid = new uid_1.Uid(); class NetronWritableStream extends stream_1.Writable { constructor({ peer, streamId, isLive = false, ...opts }) { super({ ...opts, objectMode: true }); this.index = 0; this.isClosed = false; this.cleanup = () => { this.peer.logger.debug('Cleaning up stream resources', { streamId: this.id }); this.peer.writableStreams.delete(this.id); }; this.handleError = (err) => { this.peer.logger.error('Stream error occurred', { streamId: this.id, error: err }); this.cleanup(); }; this.peer = peer; this.isLive = isLive; this.id = streamId ?? uid.next(); this.peer.logger.info('Creating writable stream', { streamId: this.id, isLive }); this.peer.writableStreams.set(this.id, this); this.once('close', this.cleanup); this.once('error', this.handleError); } async pipeFrom(source) { this.peer.logger.debug('Starting pipe operation', { streamId: this.id }); try { for await (const chunk of source) { if (!this.write(chunk)) { this.peer.logger.debug('Stream backpressure detected', { streamId: this.id }); await new Promise((resolve) => this.once('drain', resolve)); } } this.end(); this.peer.logger.debug('Pipe operation completed', { streamId: this.id }); } catch (error) { this.peer.logger.error('Pipe operation failed', { streamId: this.id, error }); this.destroy(error instanceof Error ? error : new Error(String(error))); } } _write(chunk, _, callback) { if (this.isClosed) { this.peer.logger.warn('Attempt to write to closed stream', { streamId: this.id }); callback(new Error('Stream is already closed')); return; } this.peer.logger.debug('Writing chunk', { streamId: this.id, index: this.index }); this.peer.sendStreamChunk(this.id, chunk, this.index++, false, this.isLive) .then(() => callback()) .catch((err) => { this.peer.logger.error('Error sending stream chunk', { streamId: this.id, error: err }); this.peer.sendPacket((0, packet_1.createPacket)(packet_1.Packet.nextId(), 1, packet_1.TYPE_STREAM_ERROR, { streamId: this.id, message: err.message, })).finally(() => { callback(err); this.destroy(err); }); }); } _final(callback) { if (this.isClosed) { this.peer.logger.warn('Attempt to finalize closed stream', { streamId: this.id }); callback(new Error('Stream is already closed')); return; } this.peer.logger.debug('Sending final chunk', { streamId: this.id, index: this.index }); this.peer.sendStreamChunk(this.id, null, this.index, true, this.isLive) .then(() => callback()) .catch((err) => { this.peer.logger.error('Error sending final chunk', { streamId: this.id, error: err }); callback(err); this.destroy(err); }) .finally(() => this.closeStream()); } closeStream() { if (this.isClosed) { this.peer.logger.warn('Attempt to close already closed stream', { streamId: this.id }); return; } this.peer.logger.info('Closing stream', { streamId: this.id }); this.isClosed = true; this.end(); this.cleanup(); } destroy(error) { if (this.isClosed) { this.peer.logger.warn('Attempt to destroy already closed stream', { streamId: this.id }); return this; } this.peer.logger.info('Destroying stream', { streamId: this.id, error }); this.isClosed = true; this.peer.sendStreamChunk(this.id, null, this.index, true, this.isLive) .catch((sendError) => { this.peer.logger.error('Failed to send final stream chunk', { streamId: this.id, error: sendError }); }) .finally(() => { super.destroy(error); this.cleanup(); }); return this; } static create(peer, source, isLive = false, streamId) { const stream = new NetronWritableStream({ peer, streamId, isLive }); if (source) { stream.pipeFrom(source); } return stream; } } exports.NetronWritableStream = NetronWritableStream; //# sourceMappingURL=writable-stream.js.map