{"version":3,"file":"datachannel-stream.mjs","sources":["../../../src/lib/datachannel-stream.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport * as stream from 'stream';\n\n/**\n * Turns a node-datachannel DataChannel into a real Node.js stream, complete with buffering,\n * backpressure (up to a point - if the buffer fills up, messages are dropped), and\n * support for piping data elsewhere.\n *\n * Read & written data may be either UTF-8 strings or Buffers - this difference exists at\n * the protocol level, and is preserved here throughout.\n */\nexport default class DataChannelStream extends stream.Duplex {\n  private _rawChannel: any;\n  private _readActive: boolean;\n\n  constructor(rawChannel: any, streamOptions?: Omit<stream.DuplexOptions, 'objectMode'>) {\n    super({\n      allowHalfOpen: false, // Default to autoclose on end().\n      ...streamOptions,\n      objectMode: true, // Preserve the string/buffer distinction (WebRTC treats them differently)\n    });\n\n    this._rawChannel = rawChannel;\n    this._readActive = true;\n\n    rawChannel.onMessage((msg: any) => {\n      if (!this._readActive) return; // If the buffer is full, drop messages.\n\n      // If the push is rejected, we pause reading until the next call to _read().\n      this._readActive = this.push(msg);\n    });\n\n    // When the DataChannel closes, the readable & writable ends close\n    rawChannel.onClosed(() => {\n      this.push(null);\n      this.destroy();\n    });\n\n    rawChannel.onError((errMsg: string) => {\n      this.destroy(new Error(`DataChannel error: ${errMsg}`));\n    });\n\n    // Buffer all writes until the DataChannel opens\n    if (!rawChannel.isOpen()) {\n      this.cork();\n      rawChannel.onOpen(() => this.uncork());\n    }\n  }\n\n  _read(): void {\n    // Stop dropping messages, if the buffer filling up meant we were doing so before.\n    this._readActive = true;\n  }\n\n  _write(chunk, _encoding, callback): void {\n    let sentOk;\n\n    try {\n      if (Buffer.isBuffer(chunk)) {\n        sentOk = this._rawChannel.sendMessageBinary(chunk);\n      } else if (typeof chunk === 'string') {\n        sentOk = this._rawChannel.sendMessage(chunk);\n      } else {\n        const typeName = chunk.constructor.name || typeof chunk;\n        throw new Error(`Cannot write ${typeName} to DataChannel stream`);\n      }\n    } catch (err) {\n      return callback(err);\n    }\n\n    if (sentOk) {\n      callback(null);\n    } else {\n      callback(new Error('Failed to write to DataChannel'));\n    }\n  }\n\n  _final(callback): void {\n    if (!this.allowHalfOpen) this.destroy();\n    callback(null);\n  }\n\n  _destroy(maybeErr, callback): void {\n    // When the stream is destroyed, we close the DataChannel.\n    this._rawChannel.close();\n    callback(maybeErr);\n  }\n\n  get label(): string {\n    return this._rawChannel.getLabel();\n  }\n\n  get id(): number {\n    return this._rawChannel.getId();\n  }\n\n  get protocol(): string {\n    return this._rawChannel.getProtocol();\n  }\n}\n"],"names":[],"mappings":"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"}