{"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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"}