{"ast":null,"code":"import { Observable } from '../Observable';\nimport { innerFrom } from '../observable/innerFrom';\nimport { Subject } from '../Subject';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function groupBy(keySelector, elementOrOptions, duration, connector) {\n  return operate((source, subscriber) => {\n    let element;\n\n    if (!elementOrOptions || typeof elementOrOptions === 'function') {\n      element = elementOrOptions;\n    } else {\n      ({\n        duration,\n        element,\n        connector\n      } = elementOrOptions);\n    }\n\n    const groups = new Map();\n\n    const notify = cb => {\n      groups.forEach(cb);\n      cb(subscriber);\n    };\n\n    const handleError = err => notify(consumer => consumer.error(err));\n\n    const groupBySourceSubscriber = new GroupBySubscriber(subscriber, value => {\n      try {\n        const key = keySelector(value);\n        let group = groups.get(key);\n\n        if (!group) {\n          groups.set(key, group = connector ? connector() : new Subject());\n          const grouped = createGroupedObservable(key, group);\n          subscriber.next(grouped);\n\n          if (duration) {\n            const durationSubscriber = new OperatorSubscriber(group, () => {\n              group.complete();\n              durationSubscriber === null || durationSubscriber === void 0 ? void 0 : durationSubscriber.unsubscribe();\n            }, undefined, undefined, () => groups.delete(key));\n            groupBySourceSubscriber.add(innerFrom(duration(grouped)).subscribe(durationSubscriber));\n          }\n        }\n\n        group.next(element ? element(value) : value);\n      } catch (err) {\n        handleError(err);\n      }\n    }, () => notify(consumer => consumer.complete()), handleError, () => groups.clear());\n    source.subscribe(groupBySourceSubscriber);\n\n    function createGroupedObservable(key, groupSubject) {\n      const result = new Observable(groupSubscriber => {\n        groupBySourceSubscriber.activeGroups++;\n        const innerSub = groupSubject.subscribe(groupSubscriber);\n        return () => {\n          innerSub.unsubscribe();\n          --groupBySourceSubscriber.activeGroups === 0 && groupBySourceSubscriber.teardownAttempted && groupBySourceSubscriber.unsubscribe();\n        };\n      });\n      result.key = key;\n      return result;\n    }\n  });\n}\n\nclass GroupBySubscriber extends OperatorSubscriber {\n  constructor() {\n    super(...arguments);\n    this.activeGroups = 0;\n    this.teardownAttempted = false;\n  }\n\n  unsubscribe() {\n    this.teardownAttempted = true;\n    this.activeGroups === 0 && super.unsubscribe();\n  }\n\n} //# sourceMappingURL=groupBy.js.map","map":null,"metadata":{},"sourceType":"module"}