rssh / scala-appcontext   0.1.0

GitHub

Minimalistic type-driven dependency-injection library

Scala versions: 3.x
Scala.js versions: 1.x
Scala Native versions: 0.5

Simple lightweight dependency injection

See https://github.com/rssh/notes/blob/master/2024_12_09_dependency-injection.md for motivation blog=post.

Discord channel #scala-appcontext on business4s: https://discord.gg/GCMrwpGh

Analog of UserDatabase example (see https://github.com/scala/scala3/blob/main/tests/run/Providers.scala) looks like:

case class User(name: String, email: String)

type Sql = String
extension (sc: StringContext)
    def sql(args: Any*): Sql = sc.s(args*)

class Connection {
   def runQuery(query: Sql): Unit = {
      println(s"Running query: ${query}")
   }
}

trait ConnectionPool {
   def get(): Connection
}

class UserSubscription(using UserSubscription.DependenciesProviders) {

    assert(AppContextProviders.checkAllAreNeeded)
    
    def subscribe(user: User): Unit =
      AppContext[EmailService].sendEmail(user, "You have been subscribed")
      AppContext[UserDatabase].insert(user)

  }

}

object UserSubscription extends AppContextProviderModule[UserSubscription] {
  type DependenciesProviders = AppContextProviders[(EmailService, UserDatabase)]
}

trait EmailService {
  def sendEmail(user: User, message: String): Unit = {
      println(s"Sending email to ${user.email} with message: ${message}")
  }
}

class UserDatabase(using AppContextProvider[ConnectionPool]) {

    def insert(user: User) =
      val conn = AppContext[ConnectionPool].get()
      conn.runQuery(s"insert into subscribers(name, email) values ${user.name} ${user.email}")
  }

  object UserDatabase extends AppContextProviderModule[UserDatabase] {
    type DependenciesProviders = AppContextProvider[ConnectionPool]
  }

}

test("AppContext Example3") {

    given ConnectionPool = new ConnectionPool {
      def get(): Connection = new Connection
    }

    given EmailService = new EmailService {}

    val userSubscription = AppContext[UserSubscription]
    userSubscription.subscribe(User("John", "[email protected]"))

}