-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(dsl): Offer type-safe query API (#39)
- Loading branch information
Showing
4 changed files
with
223 additions
and
16 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
34 changes: 34 additions & 0 deletions
34
modules/library/src/main/scala/zio/elasticsearch/Field.scala
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,34 @@ | ||
package zio.elasticsearch | ||
|
||
import zio.schema.{AccessorBuilder, Schema} | ||
|
||
import scala.annotation.tailrec | ||
|
||
private[elasticsearch] final case class Field[S, A](parent: Option[Field[S, _]], name: String) { self => | ||
|
||
def /[B](that: Field[A, B]): Field[S, B] = | ||
Field(that.parent.map(self / _).orElse(Some(self)), that.name) | ||
|
||
override def toString: String = { | ||
@tailrec | ||
def loop(field: Field[_, _], acc: List[String]): List[String] = field match { | ||
case Field(None, name) => s"$name" +: acc | ||
case Field(Some(parent), name) => loop(parent, s".$name" +: acc) | ||
} | ||
|
||
loop(self, Nil).mkString | ||
} | ||
} | ||
|
||
object ElasticQueryAccessorBuilder extends AccessorBuilder { | ||
override type Lens[_, S, A] = Field[S, A] | ||
override type Prism[_, S, A] = Unit | ||
override type Traversal[S, A] = Unit | ||
|
||
override def makeLens[F, S, A](product: Schema.Record[S], term: Schema.Field[S, A]): Lens[_, S, A] = | ||
Field[S, A](None, term.name) | ||
|
||
override def makePrism[F, S, A](sum: Schema.Enum[S], term: Schema.Case[S, A]): Prism[_, S, A] = () | ||
|
||
override def makeTraversal[S, A](collection: Schema.Collection[S, A], element: Schema[A]): Traversal[S, A] = () | ||
} |
41 changes: 41 additions & 0 deletions
41
modules/library/src/test/scala/zio/elasticsearch/FieldDSLSpec.scala
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,41 @@ | ||
package zio.elasticsearch | ||
|
||
import zio.schema.{DeriveSchema, Schema} | ||
import zio.test.{Spec, TestEnvironment, ZIOSpecDefault, assertTrue} | ||
|
||
object FieldDSLSpec extends ZIOSpecDefault { | ||
|
||
final case class Address(street: String, number: Int) | ||
|
||
object Address { | ||
|
||
implicit val schema: Schema.CaseClass2[String, Int, Address] = DeriveSchema.gen[Address] | ||
|
||
val (street, number) = schema.makeAccessors(ElasticQueryAccessorBuilder) | ||
} | ||
|
||
final case class Student(name: String, address: Address) | ||
|
||
object Student { | ||
|
||
implicit val schema: Schema.CaseClass2[String, Address, Student] = DeriveSchema.gen[Student] | ||
|
||
val (name, address) = schema.makeAccessors(ElasticQueryAccessorBuilder) | ||
} | ||
|
||
override def spec: Spec[TestEnvironment, Any] = | ||
suite("Field DSL")( | ||
test("properly encode single field path")( | ||
assertTrue(Field(None, "name").toString == "name") | ||
), | ||
test("properly encode single field path using accessor")( | ||
assertTrue(Student.name.toString == "name") | ||
), | ||
test("properly encode nested field path")( | ||
assertTrue(Field[Nothing, Nothing](Some(Field(None, "address")), "number").toString == "address.number") | ||
), | ||
test("properly encode nested field path using accessors")( | ||
assertTrue((Student.address / Address.number).toString == "address.number") | ||
) | ||
) | ||
} |
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