All Downloads are FREE. Search and download functionalities are using the official Maven repository.

japgolly.webapputil.indexeddb.TxnDsl.scala Maven / Gradle / Ivy

There is a newer version: 2.0.0-RC12
Show newest version
package japgolly.webapputil.indexeddb

import cats.Traverse
import japgolly.scalajs.react._
import japgolly.scalajs.react.util.Util.{identity => identityFn}
import japgolly.webapputil.indexeddb.IndexedDb.ObjectStore
import japgolly.webapputil.indexeddb.TxnMode._
import scala.collection.BuildFrom

sealed abstract class TxnDsl[M <: TxnMode] {

  implicit def catsInstance: Txn.CatsInstance[M]

  protected implicit def autoWrapStepRO[B](step: TxnStep[RO, B]): Txn[M, B]

  private implicit def autoWrapStepM[B](step: TxnStep[M, B]): Txn[M, B] =
    Txn(step)

  // Sync only. Async not allowed by IndexedDB.
  final def eval[A](c: CallbackTo[A]): Txn[M, A] =
    TxnStep.Eval(c)

  final def pure[A](a: A): Txn[M, A] =
    TxnStep.pure(a)

  @inline final def delay[A](a: => A): Txn[M, A] =
    eval(CallbackTo(a))

  final def unit: Txn[M, Unit] =
    TxnStep.unit

  @inline final def none: Txn[M, Option[Nothing]] =
    pure(None)

  final def suspend[A](a: => Txn[M, A]): Txn[M, A] =
    TxnStep.Suspend(CallbackTo(a.step))

  final def tailRec[A, B](a: A)(f: A => Txn[M, Either[A, B]]): Txn[M, B] =
    TxnStep.TailRec(a, f.andThen(_.step))

  final def objectStore[K, V](s: ObjectStoreDef.Sync[K, V]): Txn[M, ObjectStore[K, V]] =
    TxnStep.GetStore(s)

  @inline final def objectStore[K, V](s: ObjectStoreDef.Async[K, V]): Txn[M, ObjectStore[K, s.Value]] =
    objectStore(s.sync)

  @inline final def sequence[G[_], A](txns: G[Txn[M, A]])(implicit G: Traverse[G]): Txn[M, G[A]] =
    traverse(txns)(identityFn)

  @inline final def sequenceIterable[F[x] <: Iterable[x], A](txns: => F[Txn[M, A]])(implicit cbf: BuildFrom[F[Txn[M, A]], A, F[A]]): Txn[M, F[A]] =
    traverseIterable(txns)(identityFn)

  @inline final def sequenceIterable_(txns: => Iterable[Txn[M, Any]]): Txn[M, Unit] =
    traverseIterable_(txns)(identityFn)

  @inline final def sequenceOption[A](o: => Option[Txn[M, A]]): Txn[M, Option[A]] =
    traverseOption(o)(identityFn)

  @inline final def sequenceOption_(o: Option[Txn[M, Any]]): Txn[M, Unit] =
    traverseOption_(o)(identityFn)

  final def traverse[G[_], A, B](ga: G[A])(f: A => Txn[M, B])(implicit G: Traverse[G]): Txn[M, G[B]] =
    G.traverse(ga)(f.andThen(_.step))

  final def traverseIterable[F[x] <: Iterable[x], A, B](fa: => F[A])(f: A => Txn[M, B])(implicit cbf: BuildFrom[F[A], B, F[B]]): Txn[M, F[B]] =
    suspend {
      val as = fa
      val b = cbf.newBuilder(as)
      if (as.isEmpty)
        pure(b.result())
      else
        as.iterator.map(f(_).map(b += _)).reduce(_ >> _) >> delay(b.result())
    }

  final def traverseIterable_[A](fa: => Iterable[A])(f: A => Txn[M, Any]): Txn[M, Unit] =
    suspend {
      val as = fa
      val it = as.iterator
      if (it.isEmpty)
        unit
      else {
        val first = f(it.next())
        it.foldLeft(first)(_ >> f(_)).void
      }
    }

  final def traverseOption[A, B](o: => Option[A])(f: A => Txn[M, B]): Txn[M, Option[B]] =
    suspend {
      o match {
        case Some(a) => f(a).map(Some(_))
        case None    => none
      }
    }

  final def traverseOption_[A, B](o: => Option[A])(f: A => Txn[M, B]): Txn[M, Unit] =
    suspend {
      o match {
        case Some(a) => f(a).void
        case None    => unit
      }
    }

  @inline final def unless[A](cond: Boolean)(txn: => Txn[M, A]): Txn[M, Option[A]] =
    when(!cond)(txn)

  @inline final def unless_(cond: Boolean)(txn: => Txn[M, Any]): Txn[M, Unit] =
    when_(!cond)(txn)

  final def when[A](cond: Boolean)(txn: => Txn[M, A]): Txn[M, Option[A]] =
    if (cond) txn.map(Some(_)) else none

  final def when_(cond: Boolean)(txn: => Txn[M, Any]): Txn[M, Unit] =
    if (cond) txn.void else unit
}

// =====================================================================================================================

object TxnDsl {

  object RO extends TxnDsl[RO] {
    override implicit def catsInstance: Txn.CatsInstance[RO] = Txn.catsInstance(this)
    override protected implicit def autoWrapStepRO[B](s: TxnStep[RO, B]) = Txn(s)
  }

  object RW extends TxnDsl[RW] {
    override implicit def catsInstance: Txn.CatsInstance[RW] = Txn.catsInstance(this)
    override protected implicit def autoWrapStepRO[B](s: TxnStep[RO, B]) = Txn(s)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy