Packages

package definition

Linear Supertypes
AnyRef, Any
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. definition
  2. AnyRef
  3. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. Protected

Package Members

  1. package conflicts
  2. package dsl

Type Members

  1. final case class Activation(activeChoices: Map[Axis, AxisChoice]) extends AnyVal with Product with Serializable

    Selection of active choices among those available in an Activation Axis

    Selection of active choices among those available in an Activation Axis

    import distage.{Activation, Repo, Mode}
    
    Activation(
      Repo -> Repo.Prod,
      Mode -> Mode.Test,
    )
    See also

    Activation Axis

  2. trait Axis extends AnyRef
  3. sealed trait Binding extends AnyRef
  4. trait BindingTag extends AnyRef

    An attachment that can be added to a binding using its .tagged method

  5. trait BootstrapContextModule extends BootstrapModule
  6. trait BootstrapContextModuleDef extends BootstrapContextModule with ModuleDefDSL
  7. trait BootstrapModule extends ModuleBase
  8. trait BootstrapModuleDef extends BootstrapModule with ModuleDefDSL
  9. trait DIStageAnnotation extends Annotation with StaticAnnotation with TypeConstraint
  10. final class Id extends Annotation with DIStageAnnotation

    Annotation for summoning named instances.

    Annotation for summoning named instances.

    Example:

    val module = new ModuleDef {
      make[Int].named("three").from(3)
      make[Int].named("five").from(5)
    }
    
    Injector().produce(module).run {
      (five: Int @Id("five"), three: Int @Id("three")) =>
        assert(5 == five)
        assert(3 == three)
    }
    Note

    javax.inject.Named annotation is also supported

  11. abstract class Identifier extends AnyRef

    Type of a name for a named instance, which can be any type that implements izumi.distage.model.reflection.IdContract typeclass, e.g.

    Type of a name for a named instance, which can be any type that implements izumi.distage.model.reflection.IdContract typeclass, e.g. String

    Example:

    implicit val idInt: IdContract[Int] = new IdContract.IdContractImpl[Int]
    
    val module = new ModuleDef {
      make[Int].named(3).from(3)
      make[Int].named(5).from(5)
    }
  12. sealed trait ImplDef extends AnyRef
  13. trait Lifecycle[+F[_], +OuterResource] extends AnyRef

    Lifecycle is a class that describes the effectful allocation of a resource and its finalizer.

    Lifecycle is a class that describes the effectful allocation of a resource and its finalizer. This can be used to represent expensive resources.

    Resources can be created using Lifecycle.make:

    def open(file: File): Lifecycle[IO, BufferedReader] =
      Lifecycle.make(
        acquire = IO { new BufferedReader(new FileReader(file)) }
      )(release = reader => IO { reader.close() })

    Using inheritance from Lifecycle.Basic:

    final class BufferedReaderResource(
      file: File
    ) extends Lifecycle.Basic[IO, BufferedReader] {
      def acquire: IO[BufferedReader] = IO { new BufferedReader(new FileReader(file)) }
      def release(reader: BufferedReader): IO[BufferedReader] = IO { reader.close() }
    }

    Using constructor-based inheritance from Lifecycle.Make, Lifecycle.LiftF, etc:

    final class BufferedReaderResource(
      file: File
    ) extends Lifecycle.Make[IO, BufferedReader](
      acquire = IO { new BufferedReader(new FileReader(file)) },
      release = reader => IO { reader.close() },
    )

    Or by converting from an existing cats.effect.Resource or a zio.ZManaged:

    Usage is done via use:

    open(file1).use {
      reader1 =>
        open(file2).use {
          reader2 =>
            readFiles(reader1, reader2)
        }
    }

    Lifecycles can be combined into larger Lifecycles via Lifecycle#flatMap (and the associated for-comprehension syntax):

    val res: Lifecycle[IO, (BufferedReader, BufferedReader)] = {
      for {
        reader1 <- open(file1)
        reader2 <- open(file2)
      } yield (reader1, reader2)
    }

    Nested resources are released in reverse order of acquisition. Outer resources are released even if an inner use or release fails.

    Lifecycle can be used without an effect-type with Lifecycle.Simple it can also mimic Java's initialization-after-construction with Lifecycle.Mutable

    Use Lifecycle's to specify lifecycles of objects injected into the object graph.

    import distage.{Lifecycle, ModuleDef, Injector}
    import cats.effect.IO
    
    class DBConnection
    class MessageQueueConnection
    
    val dbResource = Lifecycle.make(IO { println("Connecting to DB!"); new DBConnection })(_ => IO(println("Disconnecting DB")))
    val mqResource = Lifecycle.make(IO { println("Connecting to Message Queue!"); new MessageQueueConnection })(_ => IO(println("Disconnecting Message Queue")))
    
    class MyApp(db: DBConnection, mq: MessageQueueConnection) {
      val run = IO(println("Hello World!"))
    }
    
    val module = new ModuleDef {
      make[DBConnection].fromResource(dbResource)
      make[MessageQueueConnection].fromResource(mqResource)
      make[MyApp]
    }
    
    Injector[IO]()
      .produceGet[MyApp](module)
      .use(_.run())
      .unsafeRunSync()

    Will produce the following output:

    Connecting to DB!
    Connecting to Message Queue!
    Hello World!
    Disconnecting Message Queue
    Disconnecting DB

    The lifecycle of the entire object graph is itself expressed with Lifecycle, you can control it by controlling the scope of .use or by manually invoking Lifecycle#acquire and Lifecycle#release.

    Inheritance helpers

    The following helpers allow defining Lifecycle sub-classes using expression-like syntax:

    The main reason to employ them is to workaround a limitation in Scala 2's eta-expansion — when converting a method to a function value, Scala always tries to fulfill implicit parameters eagerly instead of making them parameters of the function value, this limitation makes it harder to inject implicits using distage.

    However, when using distage's type-based syntax: make[A].fromResource[A.Resource[F]] — this limitation does not apply and implicits inject successfully.

    So to workaround the limitation you can convert an expression based resource-constructor such as:

    import distage.Lifecycle, cats.Monad
    
    class A
    object A {
      def resource[F[_]](implicit F: Monad[F]): Lifecycle[F, A] = Lifecycle.pure(new A)
    }

    Into a class-based form:

    import distage.Lifecycle, cats.Monad
    
    class A
    object A {
      final class Resource[F[_]](implicit F: Monad[F])
        extends Lifecycle.Of(
          Lifecycle.pure(new A)
        )
    }

    And inject successfully using make[A].fromResource[A.Resource[F]] syntax of izumi.distage.model.definition.dsl.ModuleDefDSL.

    The following helpers ease defining Lifecycle sub-classes using traditional inheritance where acquire/release parts are defined as methods:

    See also

    ModuleDef.fromResource

    cats.effect.Resource

    zio.ZManaged

  14. type Lifecycle2[+F[+_, +_], +E, +A] = Lifecycle[[β$0$]F[E, β$0$], A]
  15. type Lifecycle3[+F[-_, +_, +_], -R, +E, +A] = Lifecycle[[γ$1$]F[R, E, γ$1$], A]
  16. trait LifecycleTagImpl[R] extends AnyRef
  17. sealed trait LifecycleTagLowPriority extends AnyRef
  18. trait LocatorDef extends AbstractLocator with AbstractBindingDefDSL[BindDSL, BindDSLUnnamedAfterFrom, SetDSL]
  19. trait Module extends ModuleBase
  20. trait ModuleBase extends ModuleBaseInstances
  21. trait ModuleDef extends Module with ModuleDefDSL

    DSL for defining module Bindings.

    DSL for defining module Bindings.

    Example:

    class Program[F[_]: TagK: Monad] extends ModuleDef {
      make[TaglessProgram[F]]
    }
    
    object TryInterpreters extends ModuleDef {
      make[Validation.Handler[Try]].from(tryValidationHandler)
      make[Interaction.Handler[Try]].from(tryInteractionHandler)
    }
    
    // Combine modules into a full program
    val TryProgram = new Program[Try] ++ TryInterpreters

    Singleton bindings:

    • make[X] = create X using its constructor
    • make[X].from[XImpl] = bind X to its subtype XImpl using XImpl's constructor
    • make[X].from(myX) = bind X to an already existing instance myX
    • make[X].from { y: Y => new X(y) } = bind X to an instance of X constructed by a given Functoid requesting an Y parameter
    • make[X].from { y: Y @Id("special") => new X(y) } = bind X to an instance of X constructed by a given Functoid, requesting a named "special" Y parameter
    • make[X].from { y: Y => new X(y) }.annotateParameter[Y]("special") = bind X to an instance of X constructed by a given Functoid, requesting a named "special" Y parameter
    • make[X].named("special") = bind a named instance of X. It can then be summoned using Id annotation.
    • make[X].using[X]("special") = bind X to refer to another already bound named instance at key [X].named("special")
    • make[X].fromEffect(X.create[F]: F[X]) = create X using a purely-functional effect X.create in F monad
    • make[X].fromResource(X.resource[F]: Lifecycle[F, X]) = create X using a Lifecycle value specifying its creation and destruction lifecycle
    • make[X].from[XImpl].modify(fun(_)) = Create X using XImpl's constructor and apply fun to the result
    • make[X].from[XImpl].modifyBy(_.flatAp { (c: C, d: D) => (x: X) => c.method(x, d) }) = Create X using XImpl's constructor and modify its Functoid using the provided lambda - in this case by summoning additional C & D dependencies and applying C.method to X

    Set bindings:

    • many[X].add[X1].add[X2] = bind a Set of X, and add subtypes X1 and X2 created via their constructors to it. Sets can be bound in multiple different modules. All the elements of the same set in different modules will be joined together.
    • many[X].add(x1).add(x2) = add *instances* x1 and x2 to a Set[X]
    • many[X].add { y: Y => new X1(y).add { y: Y => X2(y) } = add instances of X1 and X2 constructed by a given Provider function
    • many[X].named("special").add[X1] = create a named set of X, all the elements of it are added to this named set.
    • many[X].ref[XImpl] = add a reference to an already **existing** binding of XImpl to a set of X's
    • many[X].ref[X]("special") = add a reference to an **existing** named binding of X to a set of X's

    Mutators:

    • modify[X](fun(_)) = add a modifier applying fun to the value bound at X (mutator application order is unspecified)
    • modify[X].by(_.flatAp { (c: C, d: D) => (x: X) => c.method(x, d) }) = add a modifier, applying the provided lambda to a Functoid retrieving X - in this case by summoning additional C & D dependencies and applying C.method to X

    Tags:

    • make[X].tagged("t1", "t2) = attach tags to X's binding.
    • many[X].add[X1].tagged("x1tag") = Tag a specific element of X. The tags of sets and their elements are separate.
    • many[X].tagged("xsettag") = Tag the binding of empty Set of X with a tag. The tags of sets and their elements are separate.

    Includes:

    • include(that: ModuleDef) = add all bindings in that module into this module
    See also

    TagK

    Id

    ModuleDefDSL

  22. trait ModuleMake[T <: ModuleBase] extends Aux[T, T]
  23. sealed trait TrifunctorHasLifecycleTagLowPriority extends TrifunctorHasLifecycleTagLowPriority1
  24. sealed trait TrifunctorHasLifecycleTagLowPriority1 extends AnyRef
  25. final class With[T] extends Annotation with DIStageAnnotation

    This annotation lets you choose a more specific implementation for a result of factory method other than its return type.

    This annotation lets you choose a more specific implementation for a result of factory method other than its return type.

    Example:

    trait Actor {
      def id: UUID
    }
    
    trait ActorFactory {
      @With[ActorImpl]
      def newActor(id: UUID): Actor
    }
    
    class ActorImpl(val id: UUID, someDependency: SomeDependency) extends Actor
    class SomeDependency
    
    val module = new ModuleDef {
      make[ActorFactory]
      // generated factory implementation:
      //
      // make[ActorFactory].from {
      //  (someDependency: SomeDependency) =>
      //    new ActorFactory {
      //      override def newActor(id: UUID): Actor = {
      //        new ActorImpl(id, someDependency)
      //      }
      //    }
      // }
    }
    See also

    Auto-Factories

  26. final class impl extends Annotation with DIStageAnnotation

    An optional, documentation-only annotation conveying that an abstract class or a trait is the 'actual' implementation of its supertypes and will be bound later in DI with izumi.distage.constructors.TraitConstructor or izumi.distage.constructors.FactoryConstructor

    An optional, documentation-only annotation conveying that an abstract class or a trait is the 'actual' implementation of its supertypes and will be bound later in DI with izumi.distage.constructors.TraitConstructor or izumi.distage.constructors.FactoryConstructor

    Abstract classes or traits without obvious concrete subclasses may hinder the readability of a codebase, if you still want to use them to avoid writing the full constructor, you may use this annotation to aid the reader in understanding your intentions.

    @impl abstract class Impl(
      pluser: Pluser
    ) extends PlusedInt
    See also

    Auto-Traits

    Auto-Factories

Deprecated Type Members

  1. type DIResource[+F[_], A] = Basic[F, A]
    Annotations
    @deprecated
    Deprecated

    (Since version 1.0) Use distage.Lifecycle.Basic

Value Members

  1. object Activation extends Serializable
  2. object Axis
  3. object Binding
  4. object BindingTag
  5. object Bindings
  6. object BootstrapContextModule
  7. object BootstrapModule
  8. object Identifier
  9. object ImplDef
  10. object Lifecycle extends LifecycleCatsInstances
  11. object LifecycleTagImpl extends LifecycleTagLowPriority
  12. object LifecycleTagMacro
  13. object LocatorDef
  14. object Module
  15. object ModuleBase
  16. object ModuleBaseInstances
  17. object ModuleMake
  18. object StandardAxis

Deprecated Value Members

  1. lazy val DIResource: Lifecycle.type
    Annotations
    @deprecated
    Deprecated

    (Since version 1.0) Use distage.Lifecycle

Inherited from AnyRef

Inherited from Any

Ungrouped