Skip to content

Commit

Permalink
Added project foundations
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikel authored and Mikel committed Oct 9, 2023
1 parent f49a575 commit 26f0a08
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 3 deletions.
10 changes: 7 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
lazy val root = project
.in(file("."))
.settings(
name := "scala3-example-project",
description := "Example sbt project that compiles using Scala 3",
name := "apolo",
description := "Music manager written in dotty",
version := "0.1.0",
scalaVersion := "3.3.1",
scalacOptions ++= Seq("-deprecation"),
libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test
libraryDependencies ++= Seq(
"org.scalameta" %% "munit" % "0.7.29" % Test,
"org.typelevel" %% "cats-core" % "2.9.0",
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.5",
"ch.qos.logback" % "logback-classic" % "1.2.10")
)
12 changes: 12 additions & 0 deletions src/main/scala/com/mikelalvarezgo/apolo/ApoloStarter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.mikelalvarezgo.apolo

import com.mikelalvarezgo.apolo.domain.contract.Logger
import com.mikelalvarezgo.apolo.infrastructure.dependency_injection.logger.ScalaLoggingLogger

object ApoloStarter extends App {

given logger: Logger = ScalaLoggingLogger("apolo")

logger.info("Apolo App Successfully Started!!")

}
15 changes: 15 additions & 0 deletions src/main/scala/com/mikelalvarezgo/apolo/domain/UseCase.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.mikelalvarezgo.apolo.domain

import com.mikelalvarezgo.apolo.domain.error.Validation.Validation

trait Request {
type Response
}
trait Query extends Request

trait Command extends Request {
override type Response = Unit
}
trait UseCase[T[_], R <: Request] {
def execute(r: R): Validation[T[R]]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.mikelalvarezgo.apolo.domain.contract

trait Logger {
def info(msg: String, params: Map[String, Any]): Unit
def info(msg: String, throwable: Throwable): Unit
def info(msg: String): Unit
def warning(msg: String, params: Map[String, Any]): Unit
def warning(msg: String, throwable: Throwable): Unit
def warning(msg: String): Unit
def error(msg: String, params: Map[String, Any]): Unit
def error(msg: String, throwable: Throwable): Unit
def error(msg: String): Unit
def debug(msg: String, throwable: Throwable): Unit
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.mikelalvarezgo.apolo.domain.error

trait DomainError extends Throwable {
def message: String

override def getMessage: String = message
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.mikelalvarezgo.apolo.domain.error

import scala.concurrent.Future
import scala.util.Try

import cats.data.{NonEmptyList, Validated, ValidatedNel}
import cats.implicits.catsSyntaxTry

object Validation {
type Validation[ValidType] = ValidatedNel[ValidationError, ValidType]
type ValidationFuture = Validation[Future[_]]
type ValidationFutureT[T] = Validation[Future[T]]

def fromTry[A](ve: ValidationError, t: Try[A]): Validation[A] =
t.toValidated.leftMap(_ => NonEmptyList.one(ve))

implicit final class ValidationValidIdSyntax[A](val a: A) extends AnyVal {
def validValidation[B]: Validation[A] = Validated.Valid(a)
}
implicit final class ValidationInvalidIdSyntax(val e: ValidationError) extends AnyVal {
def invalidValidation[A]: Validation[A] = Validated.invalidNel(e)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.mikelalvarezgo.apolo.domain.error

trait ValidationError extends DomainError
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.mikelalvarezgo.apolo.domain.error


import cats.data.{NonEmptyList, Validated, ValidatedNel}
import cats.implicits.catsSyntaxTry
import com.mikelalvarezgo.apolo.domain.error.Validation.Validation
final case class ValidationErrorException(
validationErrors: NonEmptyList[ValidationError],
id: Option[String]
) extends Exception {
override def getMessage: String =
(List(message) ++ fields.map { case (k, v) => s"$k=$v" }).mkString(", ")
def message: String = "Validation went wrong"
def fields: Map[String, String] =
List(Some("errors" -> validationErrors.toList.mkString(",")), id.map("id" -> _)).flatten.toMap
}

object ValidationErrorException {
def getOrThrow[T](validation: Validation[T]): T =
validation.valueOr(
validationErrors => throw ValidationErrorException(validationErrors, id = None)
)
def getOrThrowWithId[T](id: String, validation: Validation[T]): T =
validation.valueOr(
validationErrors => throw ValidationErrorException(validationErrors, id = Some(id))
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.mikelalvarezgo.apolo.infrastructure.dependency_injection

trait Context {
def dispatcher: Dispatcher
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.mikelalvarezgo.apolo.infrastructure.dependency_injection

import com.mikelalvarezgo.apolo.domain.Request
import com.mikelalvarezgo.apolo.domain.error.Validation.ValidationFutureT

trait Dispatcher {
private type ==>[A, B] = PartialFunction[A, B]

def dispatch: Request ==> ValidationFutureT[Unit]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.mikelalvarezgo.apolo.infrastructure.dependency_injection.logger

import com.mikelalvarezgo.apolo.domain.contract.Logger
import com.typesafe.scalalogging
import org.slf4j.LoggerFactory


final case class ScalaLoggingLogger(name: String) extends Logger {
private val logger: scalalogging.Logger = scalalogging.Logger(name)

override def info(msg: String, params: Map[String, Any]): Unit =
logger.info(toMessage(msg, params))
override def info(msg: String, cause: Throwable): Unit = logger.info(msg, cause)
override def info(msg: String): Unit = logger.info(msg)
def warning(msg: String, params: Map[String, Any]): Unit =
logger.warn(toMessage(msg, params))
def warning(msg: String, cause: Throwable): Unit = logger.warn(msg, cause)
def warning(msg: String): Unit = logger.warn(msg)
def error(msg: String, params: Map[String, Any]): Unit =
logger.error(toMessage(msg, params))
override def error(msg: String, cause: Throwable): Unit = logger.error(msg, cause)
def error(msg: String): Unit = logger.error(msg)
def debug(msg: String, cause: Throwable): Unit = logger.debug(msg, cause)

private def toMessage(msg: String, params: Map[String, Any]): String =
msg + ": " + params.map { case (k, v) => s"$k=$v" }.mkString(", ")
}

0 comments on commit 26f0a08

Please sign in to comment.