Skip to content

Commit

Permalink
Added /books route
Browse files Browse the repository at this point in the history
  • Loading branch information
Assayire committed Jan 13, 2024
1 parent d973b68 commit c88acf1
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 6 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# SnorriScalason

ScalaBridge Project - mentored by Noel Welsh
ScalaBridge Project - mentored by Zainab Ali & Noel Welsh


Tasks:
- Update krop to the latest version
- Change the way krop handles JSON
- Read and serve the JSON
52 changes: 52 additions & 0 deletions backend/resources/book.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"id" : "978-0641723445",
"cat" : ["book","hardcover"],
"name" : "The Lightning Thief",
"author" : "Rick Riordan",
"series_t" : "Percy Jackson and the Olympians",
"sequence_i" : 1,
"genre_s" : "fantasy",
"inStock" : true,
"price" : 12.50,
"pages_i" : 384
}
,
{
"id" : "978-1423103349",
"cat" : ["book","paperback"],
"name" : "The Sea of Monsters",
"author" : "Rick Riordan",
"series_t" : "Percy Jackson and the Olympians",
"sequence_i" : 2,
"genre_s" : "fantasy",
"inStock" : true,
"price" : 6.49,
"pages_i" : 304
}
,
{
"id" : "978-1857995879",
"cat" : ["book","paperback"],
"name" : "Sophie's World : The Greek Philosophers",
"author" : "Jostein Gaarder",
"sequence_i" : 1,
"genre_s" : "fantasy",
"inStock" : true,
"price" : 3.07,
"pages_i" : 64
}
,
{
"id" : "978-1933988177",
"cat" : ["book","paperback"],
"name" : "Lucene in Action, Second Edition",
"author" : "Michael McCandless",
"sequence_i" : 1,
"genre_s" : "IT",
"inStock" : true,
"price" : 30.50,
"pages_i" : 475
}
]

60 changes: 60 additions & 0 deletions backend/src/main/resources/book.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[
{
"id": "978-0641723445",
"name": "The Lightning Thief",
"author": "Rick Riordan",
"price": 12.50,
"pages": 384,
"genres": "fantasy",
"inStock": true,
"series_t": "Percy Jackson and the Olympians",
"sequence_i": 1,
"cat": [
"book",
"hardcover"
]
},
{
"id": "978-1423103349",
"name": "The Sea of Monsters",
"author": "Rick Riordan",
"price": 6.49,
"pages": 304,
"genres": "fantasy",
"inStock": true,
"series_t": "Percy Jackson and the Olympians",
"sequence_i": 2,
"cat": [
"book",
"paperback"
]
},
{
"id": "978-1857995879",
"name": "Sophie's World : The Greek Philosophers",
"author": "Jostein Gaarder",
"price": 3.07,
"pages": 64,
"genres": "fantasy",
"inStock": true,
"sequence_i": 1,
"cat": [
"book",
"paperback"
]
},
{
"id": "978-1933988177",
"name": "Lucene in Action, Second Edition",
"author": "Michael McCandless",
"price": 30.50,
"pages": 475,
"genres": "IT",
"inStock": true,
"sequence_i": 1,
"cat": [
"book",
"paperback"
]
}
]
19 changes: 19 additions & 0 deletions backend/src/main/scala/snorri/Book.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package snorri

import io.circe.{Encoder, Decoder}
import io.circe.generic.semiauto._

// NOTE: Not yet reading series_t,sequence_i and cat
case class Book(
id: String,
name: String,
author: String,
genres: String,
inStock: Boolean,
price: Double,
pages: Int
)

object Book:
implicit val bookEncoder: Encoder[Book] = deriveEncoder[Book]
implicit val bookDecoder: Decoder[Book] = deriveDecoder[Book]
6 changes: 5 additions & 1 deletion backend/src/main/scala/snorri/Server.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package snorri

import krop.all.*
import krop.all.given

object Server {
val app: Application = Snorri.route.otherwise(Application.notFound)
private val app: Application =
Snorri.getBooksRoute
.orElse(Snorri.echoRoute)
.orElse(Application.notFound)

@main def go(): Unit =
ServerBuilder.default.withApplication(app).run()
Expand Down
44 changes: 41 additions & 3 deletions backend/src/main/scala/snorri/Snorri.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,49 @@
package snorri

import cats.effect.IO
import io.circe.parser.decode
import io.circe.syntax.*
import io.circe.{Encoder, Json}
import krop.all.*
import krop.route.InvariantEntity
import org.http4s.circe.{CirceEntityDecoder, CirceEntityEncoder}

import scala.io.{BufferedSource, Source}

object Snorri {
val route =
private val jsonEntity: InvariantEntity[Json] =
Entity(
CirceEntityDecoder.circeEntityDecoder,
CirceEntityEncoder.circeEntityEncoder
)

val echoRoute =
Route(
Request.get(Path.root / "echo" / Param.string),
Response.ok[String]
).handle(param => s"Your message was ${param}")
Response.ok(Entity.text)
).handle(param => s"Your message was $param")

val getBooksRoute =
Route(
Request.get(Path.root / "books"),
Response.ok(jsonEntity)
).handle(() => loadBooks().asJson)

private def loadBooks(): List[Book] =
decode[List[Book]](retrieveBooks()) match {
case Right(books) => books
case Left(err) =>
err.fillInStackTrace().printStackTrace()
throw err.getCause
}

private def retrieveBooks(): String =
use(booksResource()) { src =>
src.mkString
}

private def booksResource(): BufferedSource = {
val stream = getClass.getResourceAsStream("/book.json")
Source.fromInputStream(stream)
}
}
7 changes: 7 additions & 0 deletions backend/src/main/scala/snorri/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package object snorri:
// A lame try-with-resources equivalent
def use[A <: AutoCloseable, B](resource: A)(code: A => B): B =
try
code(resource)
finally
resource.close()
5 changes: 4 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ ThisBuild / tlBaseVersion := "0.1"
ThisBuild / tlCiHeaderCheck := false

val commonSettings = Seq(
libraryDependencies += "org.creativescala" %% "krop-core" % "0.4.1"
libraryDependencies ++=
"org.creativescala" %% "krop-core" % "0.6.0" ::
Modules.circe :::
Nil
)

lazy val snorriRoot =
Expand Down
10 changes: 10 additions & 0 deletions project/Modules.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import sbt.*

object Modules {
val CirceVersion = "0.14.6"

lazy val circe: List[ModuleID] =
"io.circe" %% "circe-parser" % CirceVersion ::
"io.circe" %% "circe-generic" % CirceVersion ::
Nil
}

0 comments on commit c88acf1

Please sign in to comment.