package nova.monadic_sfx.util.reactive.store import monix.bio.Task import monix.eval.Coeval import monix.reactive.OverflowStrategy import monix.reactive.subjects.ConcurrentSubject object Store { def createL[A, M]( initialAction: A, initialState: M, reducer: Reducer[A, M], middlewares: Seq[Middleware[A, M]] = Seq.empty, overflowStrategy: OverflowStrategy.Synchronous[A] = OverflowStrategy.DropOld(50) ): Task[Store[A, M]] = Task.deferAction { implicit s => Task { val subject = ConcurrentSubject.publish[A](overflowStrategy) val fold: ((A, M), A) => Coeval[(A, M)] = { case ((_, state), action) => Coeval { val (newState, effects) = reducer(state, action) effects.subscribe(subject.onNext _) action -> newState } } val obs = subject .scanEval0F[Coeval, (A, M)]( Coeval.pure(initialAction -> initialState) )(fold) val res = middlewares .foldLeft(obs) { case (obs, middleware) => middleware(obs) } .doOnNextF(i => Coeval(println(s"Emitted item 1: $i"))) .behavior(initialAction -> initialState) .refCount // .doOnNextF(i => Coeval(println(s"Emitted item 2: $i"))) MonixProSubject.from( subject, res ) } } }