Giter Site home page Giter Site logo

zio-magic's Introduction

๐Ÿช„ zio-magic

Release Artifacts Snapshot Artifacts

Construct ZLayers automagically, with friendly compile-time hints!

// build.sbt
libraryDependencies += "io.github.kitlangton" %% "zio-magic" % "0.1.11"

What's all this then?

// Given a dependency graph (Cake needs Chocolate & Flour, which in turn need Spoon)*
//
//          Cake
//          /   \
//   Chocolate   Flour
//       |         |
//     Spoon     Spoon
//
// *Not an actual recipe.

def run(args: List[String]): URIO[ZEnv, ExitCode] = {
  
  // An effect requiring Cake and Console. Yum!
  val program: URIO[Console with Cake, Unit] =
    Cake.isDelicious.flatMap { bool => console.putStrLn(s"Cake is delicious: $bool") }

  // The old way
  val manually: ULayer[Cake with Console] =
    ((Spoon.live >>> Flour.live) ++ (Spoon.live >>> Chocolate.live)) >>> Cake.live ++ Console.live

  // The magical way (The order doesn't matter)
  val magically: UIO[Unit] =
    program.provideMagicLayer(
      Cake.live,
      Flour.live,
      Chocolate.live,
      Spoon.live,
      Console.live
    )

  magically.exitCode
}

And if you leave something off, a compile time clue!

val magically: UIO[Unit] =
  program.provideMagicLayer(
    Cake.live,
    //Flour.live, <-- Oops
    Chocolate.live,
    Spoon.live,
    Console.live
  )
๐Ÿช„  ZLayer Magic Missing Components
๐Ÿช„
๐Ÿช„  provide zio.magic.Example.Flour.Service
๐Ÿช„      for Cake.live

Versus leaving out a dependency when manually constructing your layer...

 val manually: ULayer[Cake with Console] =
   (Flour.live ++ (Spoon.live >>> Chocolate.live)) >>> Cake.live ++ Console.live
 // ^ A Spoon is missing here! 
type mismatch;
 found   : zio.ZLayer[zio.magic.Example.Spoon.Spoon with Any,Nothing,zio.magic.Example.Cake.Cake with zio.console.Console]
    (which expands to)  zio.ZLayer[zio.Has[zio.magic.Example.Spoon.Service] with Any,Nothing,zio.Has[zio.magic.Example.Cake.Service] with zio.Has[zio.console.Console.Service]]
 required: zio.ULayer[zio.magic.Example.Cake.Cake with zio.console.Console]
    (which expands to)  zio.ZLayer[Any,Nothing,zio.Has[zio.magic.Example.Cake.Service] with zio.Has[zio.console.Console.Service]]
      ((Flour.live) ++ (Spoon.live >>> Chocolate.live)) >>> Cake.live ++ Console.live

Also

You can also directly construct a ZLayer (However you must annotate the call to ZLayer.fromMagic[LikeThis], because macros).

val layer = Zlayer.fromMagic[Flour with Console](Console.live, Flour.live, Spoon.live)

To construct URLayer[In, Out] use Zlayer.fromSomeMagic[In, Out] this way:

val layer = Zlayer.fromSomeMagic[CommonEnv, Flour with Console](Console.live, Flour.live, Spoon.live)

Alternatively you can provide environment partially with provideSomeMagicLayer[Rest](l1, l2, l3) - similarly to .provideSomeLayer.

There's also .provideCustomMagicLayer for which behaves similarly to .provideCustomLayer, only it also provides ZEnv.any to all transitive dependencies.

val program: URIO[Console with Car, Unit] = ???

val carLayer: URLayer[Blocking with Wheels, Car] = ???
val wheelLayer: ULayer[Wheels] = ???

// The ZEnv you use later will provide both Blocking to carLayer and Console to the program
val provided: URIO[ZEnv, Unit] = 
  program.provideCustomMagicLayer(carLayer, wheelLayer)

Specs

provideMagicLayer, provideCustomMagicLayer, provideSomeMagicLayer, provideMagicLayerShared, provideCustomMagicLayerShared and provideSomeMagicLayerShared all work for zio-test's Spec.

Debug!

Try ZLayer.fromMagicDebug[Cake] or ZLayer.fromSomeMagicDebug[Blocking with Console, Cake] to print out a pretty graph! Ooh la la!

      Your Delicately Rendered Graph

                   Cake.live                   
               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       
         Chocolate.live         Chocolate.live  
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”              โ”‚       
   Spoon.live    Console.live     Spoon.live   
       โ”‚                              โ”‚       
 Blocking.live                   Blocking.live 

Let me know if you can think of any helpful variants, and I'll give 'em a whirl!

zio-magic's People

Contributors

hmemcpy avatar jaredmdobson avatar kitlangton avatar scala-steward avatar senia-psm avatar swoogles avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.