This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type NameRestrictions = MatchesRegex[W.`"[a-zA-Z]+[a-zA-Z0-9]*(?:[_-][a-zA-Z0-9]+)*"`.T] | |
type NamespaceRestrictions = MatchesRegex[W.`"[a-zA-Z]+[a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*"`.T] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class UserInput(name: String, namespace: String) | |
def updateVersion(input: UserInput): UserInput = { | |
val lastVersion: Int = getLatestVersion(name, namespace) | |
val schemaToStore: Schema = InputToSchemaIso.get((userInput, lastVersion + 1)) | |
val result: Schema = store(schemaToStore) | |
return InputToSchemaIso.reverseGet(result) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def updateVersion(input: UserInput): Either[String, UserInput] = | |
for { | |
name <- refineV[NameRestrictions](input.name) | |
namespace <- refineV[NamespaceRestrictions](input.namespace) | |
version = getLatestVersion(name, namespace) | |
updatedVersion <- refineV[VersionRestrictions](version.value +1) | |
result = store(Schema(name, namespace, version)) | |
} yield (UserInput(schema.name.value, schema.namespace.value)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sealed trait BusinessLogicError {val msg: String} | |
case class NonExistingSchema(name: String, namespace: String) extends BusinessLogicError { | |
override val msg: String = s"schema with name $name and namespace $namespace does not exist" | |
} | |
case class StorageError(schema: Schema) extends BusinessLogicError { | |
override val msg: String = s"schema ${schema.toString} could not be stored for whatever reason" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait AppError { | |
val message: String | |
} | |
final case class DBError(error: String) extends AppError { | |
val message = s"DBError: $error" | |
} | |
final case class UserNotFound(id: Int) extends AppError { | |
val message = s"User with id $id not found" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#BEFORE | |
def get(id: Int): Task[User] = | |
SQL | |
.get(id) | |
.option | |
.transact(tnx) | |
.foldM( | |
err => Task.fail(err), | |
maybeUser => Task.require(UserNotFound(id))(Task.succeed(maybeUser)) | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//creating | |
val maybeUser: Either[RefinedTypeError, User] = User.build(input.id, input.name) | |
//accesing | |
val id = user.id.value | |
val name = user.name.value | |
//create user in the UserService needs a for comprehension | |
def createUser(id: Int, name: String): ZIO[UserPersistence, AppError, User] = |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object User { | |
sealed abstract case class User private (id: Id, name: Name) | |
object User { | |
def build(id: Int, name: String): Either[AppError, User] = | |
for { | |
refinedId <- toRefinedId(id) | |
refinedName <- toRefinedName(name) | |
} yield new User(refinedId, refinedName) {} | |
} | |
// previous GIST with refined type stuff |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Name = String Refined NameRestrictions | |
type Id = Int Refined IdRestrictions | |
//string between 1 and 1000 characters, not all of them white | |
type NameRestrictions = Size[Interval.Closed[W.`1`.T, W.`1000`.T]] And Not[Forall[Whitespace]] | |
type IdRestrictions = Positive | |
private def toRefinedId(id: Int): Either[RefinedTypeError, Id] = | |
refineV[IdRestrictions](id).left | |
.map(_ => RefinedTypeError("must be a positive int", id.toString)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait DomainFixtures { | |
def positiveIntGen: Gen[Random, Int] = anyInt.map(num => math.abs(num) + 1) | |
def nonemptyStringGen: Gen[Random with Sized, String] = (anyASCIIString <*> anyChar).map(elems => elems._1 + elems._2) | |
def userGen: Gen[Random with Sized, User] = | |
(positiveIntGen <*> nonemptyStringGen).map(elems => | |
User.build(elems._1, elems._2).getOrElse(throw new Exception("Exception in test building customer")) | |
) | |
} |
OlderNewer