Skip to content

Commit

Permalink
Merge pull request #55 from SwissDataScienceCenter/move-model-classes
Browse files Browse the repository at this point in the history
chore: Move name and id to a common namespace
  • Loading branch information
eikek authored Mar 12, 2024
2 parents 898a39f + da6fac2 commit f504f33
Show file tree
Hide file tree
Showing 32 changed files with 328 additions and 233 deletions.
13 changes: 13 additions & 0 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
rules = [
OrganizeImports
]
OrganizeImports {
coalesceToWildcardImportThreshold = 3
expandRelative = true
groupedImports = Keep
importsOrder = Ascii
groups = ["re:javax?\\.", "scala.", "re:(cats|fs2)\\.", "*"]
importSelectorsOrder = Ascii
removeUnused = false
targetDialect = Scala3
}
2 changes: 2 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ lazy val commonSettings = Seq(
),
Compile / console / scalacOptions := (Compile / scalacOptions).value.filterNot(_ == "-Xfatal-warnings"),
Test / console / scalacOptions := (Compile / console / scalacOptions).value,
semanticdbEnabled := true, // enable SemanticDB
semanticdbVersion := scalafixSemanticdb.revision,
libraryDependencies ++=
Dependencies.scribe,
libraryDependencies ++= (
Expand Down
29 changes: 29 additions & 0 deletions modules/commons/src/main/scala/io/renku/search/model/Id.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 Swiss Data Science Center (SDSC)
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
* Eidgenössische Technische Hochschule Zürich (ETHZ).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.renku.search.model

import io.bullet.borer.Codec
import io.github.arainko.ducktape.Transformer

opaque type Id = String
object Id:
def apply(v: String): Id = v
extension (self: Id) def value: String = self
given Transformer[String, Id] = apply
given Codec[Id] = Codec.of[String]
29 changes: 29 additions & 0 deletions modules/commons/src/main/scala/io/renku/search/model/Name.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 Swiss Data Science Center (SDSC)
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
* Eidgenössische Technische Hochschule Zürich (ETHZ).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.renku.search.model

import io.bullet.borer.Codec
import io.github.arainko.ducktape.Transformer

opaque type Name = String
object Name:
def apply(v: String): Name = v
extension (self: Name) def value: String = self
given Transformer[String, Name] = apply
given Codec[Name] = Codec.of[String]
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,16 @@

package io.renku.search.model

import java.time.Instant

import cats.kernel.Order

import io.bullet.borer.derivation.MapBasedCodecs.*
import io.bullet.borer.{Codec, Decoder, Encoder}
import io.github.arainko.ducktape.*
import io.renku.search.borer.codecs.all.given

import java.time.Instant

object projects:

opaque type Id = String
object Id:
def apply(v: String): Id = v
extension (self: Id) def value: String = self
given Transformer[String, Id] = apply
given Codec[Id] = Codec.of[String]

opaque type Name = String
object Name:
def apply(v: String): Name = v
extension (self: Name) def value: String = self
given Transformer[String, Name] = apply
given Codec[Name] = Codec.of[String]

opaque type Slug = String
object Slug:
def apply(v: String): Slug = v
Expand Down Expand Up @@ -83,8 +69,6 @@ object projects:

object Visibility:
given Order[Visibility] = Order.by(_.ordinal)
given Decoder[Visibility] = Decoder.forString.map(Visibility.unsafeFromString)
given Encoder[Visibility] = Encoder.forString.contramap(_.name)

def unsafeFromString(v: String): Visibility =
valueOf(v.toLowerCase.capitalize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,6 @@ import io.github.arainko.ducktape.Transformer

object users:

opaque type Id = String
object Id:
def apply(v: String): Id = v
extension (self: Id) def value: String = self
given Transformer[String, Id] = apply
given Codec[Id] = Codec.bimap[String, Id](_.value, Id.apply)

opaque type FirstName = String
object FirstName:
def apply(v: String): FirstName = v
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@

package io.renku.search.model

import java.time.Instant
import java.time.temporal.ChronoUnit

import cats.syntax.all.*

import org.scalacheck.Gen
import org.scalacheck.cats.implicits.*

import java.time.Instant
import java.time.temporal.ChronoUnit

object ModelGenerators:

val projectNameGen: Gen[projects.Name] =
alphaStringGen(max = 10).map(projects.Name.apply)
val idGen: Gen[Id] = Gen.uuid.map(uuid => Id(uuid.toString))
val nameGen: Gen[Name] =
alphaStringGen(max = 10).map(Name.apply)
val projectDescGen: Gen[projects.Description] =
alphaStringGen(max = 30).map(projects.Description.apply)

Expand All @@ -52,7 +53,6 @@ object ModelGenerators:
.chooseNum(min.toEpochMilli, max.toEpochMilli)
.map(Instant.ofEpochMilli(_).truncatedTo(ChronoUnit.MILLIS))

val userIdGen: Gen[users.Id] = Gen.uuid.map(uuid => users.Id(uuid.toString))
val userFirstNameGen: Gen[users.FirstName] = Gen
.oneOf("Eike", "Kuba", "Ralf", "Lorenzo", "Jean-Pierre", "Alfonso")
.map(users.FirstName.apply)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@ package io.renku.search.api

import cats.effect.Async
import cats.syntax.all.*

import io.github.arainko.ducktape.*
import io.renku.search.api.data.*
import io.renku.search.model.users
import io.renku.search.model.EntityType
import io.renku.search.model.Id
import io.renku.search.solr.client.SearchSolrClient
import io.renku.search.solr.documents.Entity as SolrEntity
import io.renku.search.solr.schema.EntityDocumentSchema.Fields
import io.renku.solr.client.QueryResponse
import io.renku.solr.client.facet.FacetResponse
import org.http4s.dsl.Http4sDsl
import scribe.Scribe
import io.renku.search.model.EntityType
import io.renku.solr.client.facet.FacetResponse

private class SearchApiImpl[F[_]: Async](solrClient: SearchSolrClient[F])
extends Http4sDsl[F]
Expand Down Expand Up @@ -76,5 +77,5 @@ private class SearchApiImpl[F[_]: Async](solrClient: SearchSolrClient[F])
else SearchResult(items, facets, pageInfo)

private lazy val toApiEntity: SolrEntity => SearchEntity =
given Transformer[users.Id, UserId] = (id: users.Id) => UserId(id)
given Transformer[Id, UserId] = (id: Id) => UserId(id)
_.to[SearchEntity]
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@

package io.renku.search.api.data

import io.bullet.borer.*
import java.time.Instant

import io.bullet.borer.NullOptions.given
import io.bullet.borer.*
import io.bullet.borer.derivation.MapBasedCodecs.{deriveAllCodecs, deriveCodec}
import io.renku.search.model.*
import io.renku.search.api.tapir.SchemaSyntax.*
import io.renku.search.model.*
import sttp.tapir.Schema.SName
import sttp.tapir.SchemaType.{SCoproduct, SDateTime, SProductField, SRef}
import sttp.tapir.SchemaType._
import sttp.tapir.generic.Configuration
import sttp.tapir.{FieldName, Schema, SchemaType}

import java.time.Instant

sealed trait SearchEntity

final case class Project(
id: projects.Id,
name: projects.Name,
id: Id,
name: Name,
slug: projects.Slug,
repositories: Seq[projects.Repository],
visibility: projects.Visibility,
Expand All @@ -45,8 +45,8 @@ final case class Project(
) extends SearchEntity

object Project:
private given Schema[projects.Id] = Schema.string[projects.Id]
private given Schema[projects.Name] = Schema.string[projects.Name]
private given Schema[Id] = Schema.string[Id]
private given Schema[Name] = Schema.string[Name]
private given Schema[projects.Slug] = Schema.string[projects.Slug]
private given Schema[projects.Repository] = Schema.string[projects.Repository]
private given Schema[projects.Visibility] =
Expand All @@ -57,45 +57,45 @@ object Project:
.derived[Project]
.jsonExample(
Project(
projects.Id("01HRA7AZ2Q234CDQWGA052F8MK"),
projects.Name("renku"),
Id("01HRA7AZ2Q234CDQWGA052F8MK"),
Name("renku"),
projects.Slug("renku"),
Seq(projects.Repository("https://github.com/renku")),
projects.Visibility.Public,
Some(projects.Description("Renku project")),
UserId(users.Id("1CAF4C73F50D4514A041C9EDDB025A36")),
UserId(Id("1CAF4C73F50D4514A041C9EDDB025A36")),
projects.CreationDate(Instant.now),
Some(1.0)
): SearchEntity
)

final case class UserId(id: users.Id)
final case class UserId(id: Id)
object UserId:
given Codec[UserId] = deriveCodec[UserId]

private given Schema[users.Id] = Schema.string[users.Id]
private given Schema[Id] = Schema.string[Id]
given Schema[UserId] = Schema
.derived[UserId]
.jsonExample(UserId(users.Id("01HRA7AZ2Q234CDQWGA052F8MK")))
.jsonExample(UserId(Id("01HRA7AZ2Q234CDQWGA052F8MK")))

final case class User(
id: users.Id,
id: Id,
firstName: Option[users.FirstName] = None,
lastName: Option[users.LastName] = None,
email: Option[users.Email] = None,
score: Option[Double] = None
) extends SearchEntity

object User:
private given Schema[users.Id] = Schema.string[users.Id]
private given Schema[Id] = Schema.string[Id]
private given Schema[users.FirstName] = Schema.string[users.FirstName]
private given Schema[users.LastName] = Schema.string[users.LastName]
private given Schema[users.Email] = Schema.string[users.Email]
given Schema[User] = Schema
.derived[User]
.jsonExample(
User(
users.Id("1CAF4C73F50D4514A041C9EDDB025A36"),
Id("1CAF4C73F50D4514A041C9EDDB025A36"),
Some(users.FirstName("Albert")),
Some(users.LastName("Einstein")),
Some(users.Email("[email protected]")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ package io.renku.search.api

import cats.effect.IO
import cats.syntax.all.*

import io.github.arainko.ducktape.*
import io.renku.search.GeneratorSyntax.*
import io.renku.search.api.data.*
import io.renku.search.model.users
import io.renku.search.model.Id
import io.renku.search.model.users.FirstName
import io.renku.search.query.Query
import io.renku.search.solr.client.SearchSolrSpec
import io.renku.search.solr.client.SolrDocumentGenerators.*
Expand Down Expand Up @@ -53,7 +55,7 @@ class SearchApiSpec extends CatsEffectSuite with SearchSolrSpec:
test("return Project and User entities"):
withSearchSolrClient().use { client =>
val project = projectDocumentGen("exclusive", "exclusive description").generateOne
val user = SolrUser(project.createdBy, users.FirstName("exclusive").some)
val user = SolrUser(project.createdBy, FirstName("exclusive").some)
val searchApi = new SearchApiImpl[IO](client)
for {
_ <- client.insert(project :: user :: Nil)
Expand All @@ -75,5 +77,5 @@ class SearchApiSpec extends CatsEffectSuite with SearchSolrSpec:
private def toApiEntities(e: SolrEntity*) = e.map(toApiEntity)

private def toApiEntity(e: SolrEntity) =
given Transformer[users.Id, UserId] = (id: users.Id) => UserId(id)
given Transformer[Id, UserId] = (id: Id) => UserId(id)
e.to[SearchEntity]
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ package project
import cats.Show
import cats.effect.{Async, Resource}
import fs2.io.net.Network

import io.renku.avro.codec.decoders.all.given
import io.renku.events.v1.ProjectAuthorizationAdded
import io.renku.redis.client.{QueueName, RedisConfig}
import io.renku.search.model.users
import io.renku.search.model.Id
import io.renku.search.provision.TypeTransformers.given
import io.renku.search.solr.documents
import io.renku.solr.client.SolrConfig
Expand Down Expand Up @@ -60,7 +61,7 @@ object AuthorizationAddedProvisioning:
: ((ProjectAuthorizationAdded, documents.Project)) => documents.Project = {
case (update, orig) =>
orig.addMember(
users.Id(update.userId),
Id(update.userId),
memberRoleTransformer.transform(update.role)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ package io.renku.search.provision
package project

import cats.Show
import cats.effect.{Async, Resource}
import cats.effect.Async
import cats.effect.Resource
import fs2.io.net.Network

import io.renku.avro.codec.decoders.all.given
import io.renku.events.v1.ProjectAuthorizationRemoved
import io.renku.redis.client.{QueueName, RedisConfig}
import io.renku.search.model.users
import io.renku.redis.client.QueueName
import io.renku.redis.client.RedisConfig
import io.renku.search.model.Id
import io.renku.search.solr.documents
import io.renku.solr.client.SolrConfig
import scribe.Scribe
Expand Down Expand Up @@ -58,5 +61,5 @@ object AuthorizationRemovedProvisioning:
private lazy val docUpdate
: ((ProjectAuthorizationRemoved, documents.Project)) => documents.Project = {
case (update, orig) =>
orig.removeMember(users.Id(update.userId))
orig.removeMember(Id(update.userId))
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ package project
import cats.Show
import cats.effect.{Async, Resource}
import fs2.io.net.Network

import io.renku.avro.codec.decoders.all.given
import io.renku.events.v1.ProjectAuthorizationUpdated
import io.renku.redis.client.{QueueName, RedisConfig}
import io.renku.search.model.users
import io.renku.search.model.Id
import io.renku.search.provision.TypeTransformers.given
import io.renku.search.solr.documents
import io.renku.solr.client.SolrConfig
Expand Down Expand Up @@ -60,7 +61,7 @@ object AuthorizationUpdatedProvisioning:
: ((ProjectAuthorizationUpdated, documents.Project)) => documents.Project = {
case (update, orig) =>
orig.addMember(
users.Id(update.userId),
Id(update.userId),
memberRoleTransformer.transform(update.role)
)
}
Loading

0 comments on commit f504f33

Please sign in to comment.