(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports", "rxjs", "rxjs/operators", "../creators/ws", "./send", "./consume"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require("rxjs"), require("rxjs/operators"), require("../creators/ws"), require("./send"), require("./consume"));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.rxjs, global.operators, global.ws, global.send, global.consume);
    global.conduit = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _rxjs, _operators, _ws2, _send2, _consume2) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.default = _exports.testExports = void 0;
  _ws2 = _interopRequireDefault(_ws2);
  _send2 = _interopRequireDefault(_send2);
  _consume2 = _interopRequireDefault(_consume2);

  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

  const errors = {
    noUrl: () => new Error('conduit operator requires a {url<String>}')
  };

  function createMessageBuffer(ws$) {
    return messageIn$ => {
      const wsSub$ = ws$.pipe((0, _operators.share)());

      const closeBuffer = () => wsSub$.pipe((0, _operators.map)(([socket]) => socket && socket.readyState === 1), (0, _operators.pairwise)(), (0, _operators.filter)(([wasConnected, nowConnected]) => !wasConnected && nowConnected));

      const bufferedMessage$ = messageIn$.pipe((0, _operators.withLatestFrom)((0, _rxjs.merge)((0, _rxjs.of)([null, null]), wsSub$)), (0, _operators.filter)(([, [socket]]) => !socket || socket.readyState !== 1), (0, _operators.map)(([message]) => message), (0, _operators.bufferWhen)(closeBuffer), (0, _operators.mergeMap)(bufferedItems => (0, _rxjs.of)(...bufferedItems)));
      return bufferedMessage$;
    };
  }

  function passthroughMessageBuffer(ws$) {
    return messageIn$ => messageIn$.pipe((0, _operators.withLatestFrom)((0, _rxjs.merge)((0, _rxjs.of)([null, null]), ws$)), (0, _operators.filter)(([, [socket]]) => socket && socket.readyState === 1), (0, _operators.map)(([message]) => message));
  }

  function bufferMessages(ws$, _createMessageBuffer = createMessageBuffer, _passthroughMessageBuffer = passthroughMessageBuffer) {
    return messageIn$ => {
      const messageInSub$ = messageIn$.pipe((0, _operators.share)());
      const wsSub$ = ws$.pipe((0, _operators.share)());
      const bufferedMessage$ = messageInSub$.pipe(_createMessageBuffer(wsSub$));
      const unbufferedMessage$ = messageInSub$.pipe(_passthroughMessageBuffer(wsSub$));
      return (0, _rxjs.merge)(bufferedMessage$, unbufferedMessage$);
    };
  }

  const conduit = function conduit({
    url,
    bufferOnDisconnect = true,
    socketOptions = {},
    protocols = null,
    stop$ = (0, _rxjs.of)(),
    serializer = JSON.stringify,
    deserializer = JSON.parse,
    _send = _send2.default,
    _consume = _consume2.default,
    _ws = _ws2.default,
    _bufferMessages = bufferMessages
  } = {}) {
    if (!url) return () => (0, _rxjs.throwError)(errors.noUrl());
    return messageIn$ => {
      const messageInSub$ = messageIn$.pipe((0, _operators.shareReplay)(1));

      const ws$ = _ws({
        url,
        protocols,
        socketOptions
      }).pipe((0, _operators.takeUntil)(stop$), (0, _operators.shareReplay)(1));

      const producer$ = messageIn$.pipe(bufferOnDisconnect ? _bufferMessages(ws$) : (0, _operators.tap)(() => true), (0, _operators.takeUntil)(stop$), _send(ws$, serializer), (0, _operators.filter)(() => false));
      const consumer$ = ws$.pipe(_consume(deserializer));
      return (0, _rxjs.merge)(producer$, consumer$);
    };
  };

  const testExports = {
    createMessageBuffer
  };
  _exports.testExports = testExports;
  var _default = conduit;
  _exports.default = _default;
});
//# sourceMappingURL=conduit.js.map