-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e7a5f15
commit 3f33988
Showing
7 changed files
with
368 additions
and
75 deletions.
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package update.search | ||
|
||
import tui.TUI | ||
import tui.components.Choose | ||
import update.{Artifact, Group, Version} | ||
import view.View | ||
import zio._ | ||
import zio.json._ | ||
|
||
import java.net.URLEncoder | ||
import java.time.Instant | ||
import scala.annotation.tailrec | ||
|
||
final case class Payload( | ||
response: Response | ||
) | ||
|
||
object Payload { | ||
implicit val codec: JsonCodec[Payload] = | ||
DeriveJsonCodec.gen[Payload] | ||
} | ||
|
||
final case class Response( | ||
numFound: Int, | ||
start: Int, | ||
docs: List[Doc] | ||
) | ||
|
||
object Response { | ||
implicit val codec: JsonCodec[Response] = | ||
DeriveJsonCodec.gen[Response] | ||
} | ||
|
||
final case class Doc( | ||
id: String, | ||
g: String, | ||
a: String, | ||
latestVersion: String, | ||
timestamp: Long | ||
) | ||
|
||
final case class SearchResult( | ||
group: Group, | ||
artifact: Artifact, | ||
scalaVersions: List[String], | ||
latestVersion: Version, | ||
lastUpdated: Instant | ||
) { | ||
def render: View = | ||
View.horizontal( | ||
View.text(s"\"${group.value}\"").blue, | ||
View.text("%%").blue.dim, | ||
View.text(s"\"${artifact.value}\"").blue, | ||
View.text("%").blue.dim, | ||
View.text(s"\"${latestVersion.value}\"").blue | ||
) | ||
} | ||
|
||
object SearchResult { | ||
def fromDoc(doc: Doc): SearchResult = { | ||
val (artifact, scalaVersion) = | ||
doc.a match { | ||
case s"${artifact}_sjs1_2.11" => | ||
(artifact, "sjs1_2.11") | ||
case s"${artifact}_sjs1_2.12" => | ||
(artifact, "sjs1_2.12") | ||
case s"${artifact}_sjs1_2.13" => | ||
(artifact, "sjs1_2.13") | ||
case s"${artifact}_sjs1_3" => | ||
(artifact, "sjs1_3") | ||
case s"${artifact}_2.11" => | ||
(artifact, "2.11") | ||
case s"${artifact}_2.12" => | ||
(artifact, "2.12") | ||
case s"${artifact}_2.13" => | ||
(artifact, "2.13") | ||
case s"${artifact}_3" => | ||
(artifact, "3") | ||
case other => | ||
(other, "OOPS") | ||
} | ||
|
||
SearchResult( | ||
Group(doc.g), | ||
Artifact(artifact), | ||
List(scalaVersion), | ||
Version(doc.latestVersion), | ||
Instant.ofEpochMilli(doc.timestamp) | ||
) | ||
} | ||
|
||
// Combine results with same group, artifact and latestVersion but different scala versions | ||
def combineResults(results: List[SearchResult]): List[SearchResult] = { | ||
@tailrec | ||
def loop( | ||
results: List[SearchResult], | ||
acc: List[SearchResult] | ||
): List[SearchResult] = | ||
(results, acc) match { | ||
case (Nil, acc) => acc.reverse | ||
case (r :: rs, a :: as) | ||
if a.group == r.group && a.artifact == r.artifact && a.latestVersion == r.latestVersion => | ||
loop(rs, a.copy(scalaVersions = a.scalaVersions ++ r.scalaVersions) :: as) | ||
case (r :: rs, acc) => | ||
loop(rs, r :: acc) | ||
} | ||
|
||
loop(results, Nil) | ||
} | ||
|
||
} | ||
|
||
object Doc { | ||
implicit val codec: JsonCodec[Doc] = | ||
DeriveJsonCodec.gen[Doc] | ||
} | ||
|
||
final case class Search() { | ||
|
||
def search(query: String): ZIO[Any, Throwable, List[SearchResult]] = { | ||
val urlEncodedQuery = URLEncoder.encode(query, "UTF-8") | ||
val url = s"https://search.maven.org/solrsearch/select?q=$urlEncodedQuery&start=0&rows=60" | ||
for { | ||
string <- ZIO.attempt { | ||
val source = scala.io.Source.fromURL(url) | ||
val string = source.mkString | ||
source.close() | ||
string | ||
} | ||
payload <- ZIO.from(string.fromJson[Payload]).mapError(new Error(_)) | ||
} yield SearchResult | ||
.combineResults(payload.response.docs.map(SearchResult.fromDoc)) | ||
.distinctBy(sr => (sr.group, sr.artifact, sr.latestVersion)) | ||
} | ||
|
||
} | ||
|
||
object SearchExample extends ZIOAppDefault { | ||
|
||
val run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] = { | ||
for { | ||
_ <- ZIO.unit | ||
search = Search() | ||
results <- search.search("zio-cli") | ||
// _ <- Choose.run(results)(_.render) | ||
_ <- ZIO.debug( | ||
View | ||
.vertical( | ||
Chunk( | ||
View.text("LATEST PACKAGES").blue, | ||
View.text("───────────────").blue.dim | ||
) ++ | ||
results.map(_.render): _* | ||
) | ||
.render(100, 10) | ||
) | ||
} yield results | ||
}.provide(TUI.live(false)) | ||
|
||
} |
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
Oops, something went wrong.