Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework the Scaladex API #1345

Merged
merged 1 commit into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ lazy val core = crossProject(JSPlatform, JVMPlatform)
"io.github.cquiroz" %%% "scala-java-time" % "2.5.0",
"com.typesafe.play" %%% "play-json" % V.playJson,
"org.endpoints4s" %%% "algebra" % "1.11.1",
"org.endpoints4s" %% "json-schema-playjson" % "1.11.1" % Test,
"org.scalatest" %%% "scalatest" % V.scalatest % Test,
"org.jsoup" % "jsoup" % "1.17.2"
) ++ Seq(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package scaladex.core.api

import java.time.Instant

import scaladex.core.model.Artifact
import scaladex.core.model.Language
import scaladex.core.model.License
import scaladex.core.model.Platform
import scaladex.core.model.Project
import scaladex.core.model.SemanticVersion

final case class ArtifactResponse(
groupId: Artifact.GroupId,
artifactId: String,
version: SemanticVersion,
artifactName: Artifact.Name,
project: Project.Reference,
releaseDate: Instant,
licenses: Seq[License],
language: Language,
platform: Platform
)

object ArtifactResponse {
def apply(artifact: Artifact): ArtifactResponse = ArtifactResponse(
artifact.groupId,
artifact.artifactId,
artifact.version,
artifact.artifactName,
artifact.projectRef,
artifact.releaseDate,
artifact.licenses.toSeq,
artifact.language,
artifact.platform
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import scaladex.core.model.search.Sorting

case class AutocompletionParams(
query: String,
you: Boolean,
topics: Seq[String],
languages: Seq[String],
platforms: Seq[String],
contributingSearch: Boolean
contributingSearch: Boolean,
you: Boolean
) {
def withUser(user: Option[UserState]): SearchParams = {
val userRepos = if (you) user.map(_.repos).getOrElse(Set.empty) else Set.empty[Project.Reference]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package scaladex.core.api

import scaladex.core.model.Artifact
import scaladex.core.model.Project

trait Endpoints
extends JsonSchemas
with endpoints4s.algebra.Endpoints
with endpoints4s.algebra.JsonEntitiesFromSchemas {

private val projectPath: Path[Project.Reference] =
(segment[String]("organization") / segment[String]("repository"))
.xmap { case (org, repo) => Project.Reference.from(org, repo) }(ref =>
(ref.organization.value, ref.repository.value)
)

private val artifactPath: Path[Artifact.MavenReference] =
(segment[String]("groupId") / segment[String]("artifactId") / segment[String]("version"))
.xmap { case (groupId, artifactId, version) => Artifact.MavenReference(groupId, artifactId, version) }(ref =>
(ref.groupId, ref.artifactId, ref.version)
)

private val autocompletionQueryString: QueryString[AutocompletionParams] = (
qs[String]("q", docs = Some("Main query (e.g., 'json', 'testing', etc.)")) &
qs[Seq[String]]("topics", docs = Some("Filter on Github topics")) &
qs[Seq[String]](
"languages",
docs = Some("Filter on language versions (e.g., '3', '2.13', '2.12', '2.11', 'java')")
) &
qs[Seq[String]](
"platforms",
docs = Some("Filter on runtime platforms (e.g., 'jvm', 'sjs1', 'native0.4', 'sbt1.0')")
) &
qs[Option[Boolean]]("contributingSearch").xmap(_.getOrElse(false))(Option.when(_)(true)) &
qs[Option[String]]("you", docs = Some("internal usage")).xmap[Boolean](_.contains("✓"))(Option.when(_)("✓"))
).xmap((AutocompletionParams.apply _).tupled)(Function.unlift(AutocompletionParams.unapply))

val listProjects: Endpoint[Unit, Seq[Project.Reference]] =
endpoint(
get(path / "api" / "projects"),
ok(jsonResponse[Seq[Project.Reference]])
)

val listProjectArtifacts: Endpoint[Project.Reference, Seq[Artifact.MavenReference]] =
endpoint(
get(path / "api" / "projects" / projectPath / "artifacts"),
ok(jsonResponse[Seq[Artifact.MavenReference]])
)

val getArtifact: Endpoint[Artifact.MavenReference, Option[ArtifactResponse]] =
endpoint(
get(path / "api" / "artifacts" / artifactPath),
ok(jsonResponse[ArtifactResponse]).orNotFound()
)

val autocomplete: Endpoint[AutocompletionParams, Seq[AutocompletionResponse]] =
endpoint(
get(path / "api" / "autocomplete" /? autocompletionQueryString),
ok(jsonResponse[Seq[AutocompletionResponse]])
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package scaladex.core.api

import java.time.Instant

import scaladex.core.model.Artifact
import scaladex.core.model.Language
import scaladex.core.model.License
import scaladex.core.model.Platform
import scaladex.core.model.Project
import scaladex.core.model.SemanticVersion

/**
* The Json schema of the Scaladex API
*/
trait JsonSchemas extends endpoints4s.algebra.JsonSchemas {
implicit val projectReferenceSchema: JsonSchema[Project.Reference] =
field[String]("organization")
.zip(field[String]("repository"))
.xmap(Function.tupled(Project.Reference.from(_, _)))(ref => (ref.organization.value, ref.repository.value))

implicit val mavenReferenceSchema: JsonSchema[Artifact.MavenReference] =
field[String]("groupId")
.zip(field[String]("artifactId"))
.zip(field[String]("version"))
.xmap(Function.tupled(Artifact.MavenReference.apply _))(Function.unlift(Artifact.MavenReference.unapply))

implicit val getArtifactResponseSchema: JsonSchema[ArtifactResponse] =
field[String]("groupId")
.xmap(Artifact.GroupId.apply)(_.value)
.zip(field[String]("artifactId"))
.zip(field[String]("version").xmap(SemanticVersion.from)(_.encode))
.zip(field[String]("artifactName").xmap(Artifact.Name.apply)(_.value))
.zip(field[String]("project").xmap(Project.Reference.from)(_.toString))
.zip(field[Long]("releaseDate").xmap(Instant.ofEpochMilli)(_.toEpochMilli))
.zip(field[Seq[String]]("licenses").xmap(_.flatMap(License.get))(_.map(_.shortName)))
.zip(field[String]("language").xmap(Language.fromLabel(_).get)(_.label))
.zip(field[String]("platform").xmap(Platform.fromLabel(_).get)(_.label))
.xmap {
case (groupId, artifactId, version, artifactName, project, releaseDate, licenses, language, platform) =>
ArtifactResponse(
groupId,
artifactId,
version,
artifactName,
project,
releaseDate,
licenses,
language,
platform
)
}(Function.unlift(ArtifactResponse.unapply))

implicit val autocompletionResponseSchema: JsonSchema[AutocompletionResponse] =
field[String]("organization")
.zip(field[String]("repository"))
.zip(field[String]("description"))
.xmap[AutocompletionResponse] {
case (organization, repository, description) => AutocompletionResponse(organization, repository, description)
} { autocompletionResponse =>
(autocompletionResponse.organization, autocompletionResponse.repository, autocompletionResponse.description)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package scaladex.core.api

final case class ProjectParams(language: Option[String], platform: Option[String])

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import java.time.format.DateTimeFormatter
import fastparse.P
import fastparse.Start
import fastparse._
import scaladex.core.api.artifact.ArtifactMetadataResponse
import scaladex.core.model.PatchVersion
import scaladex.core.util.Parsers._

Expand Down Expand Up @@ -302,13 +301,4 @@ object Artifact {
def repoUrl: String =
s"https://repo1.maven.org/maven2/${groupId.replace('.', '/')}/$artifactId/$version/"
}

def toMetadataResponse(artifact: Artifact): ArtifactMetadataResponse =
ArtifactMetadataResponse(
version = artifact.version.toString,
projectReference = Some(artifact.projectRef.toString),
releaseDate = artifact.releaseDate.toString,
language = artifact.language.toString,
platform = artifact.platform.toString
)
}
Loading