Skip to main content
Version: 2.x

High Level API

The high level API relies on two mechanisms to provide type safety and reduce boilerplate code:

  1. Automatic ZIO Schema derivation for case classes
  2. Semi automatic generation of ProjectionExpression's for case classes and sealed traits

ZIO Schema derivation​

The High Level API methods rely on a ZIO Schema for a particular type being in implicit scope. This is achieved using the DeriveSchema.gen macro. Internally codecs are automatically generated for the case classes based on the meta data provided by the Schema's.

final case class Person(id: String, name: String)
object Person {
implicit val schema: Schema.CaseClass2[String, String, Person] = DeriveSchema.gen[Person]
}

Projection Expression generation​

The automated generation of ProjectionExpression's is achieved using the ProjectionExpression.accessors method. For classes this method generates a ProjectionExpression for each field. For sealed traits it generates a ProjectionExpression for each child.

final case class Person(id: String, name: String)
object Person {
implicit val schema // ...

val (id, name) = ProjectionExpression.accessors[Person]
}

Using a ProjectionExpression as a springboard to creating further expressions​

In the above example Person.id and Person.name are ProjectionExpressions automatically generated by the ProjectionExpression.accessors method. They are used as a springboard for creating further type safe APIs eg

  • Person.id === "1" creates a ConditionExpression
  • Person.name.set("Smith") creates an UpdateExpression
  • Person.id.partitionKey === "1" creates a primary key expression

DynamoDBQuery CRUD methods​

There are also type safe query creation methods in the DynamoDBQuery companion object such as get, put, update, deleteFrom, queryAll and all these take expressions as arguments. So taking our example further we can see how all these APIs can be used together to create a type safe CRUD queries:

final case class Person(id: String, name: String)
object Person {
implicit val schema: Schema.CaseClass2[String, String, Person] = DeriveSchema.gen[Person]
val (id, name) = ProjectionExpression.accessors[Person]
}

val table = "person-table"
val person = Person("1", "John")
for {
_ <- DynamoDBQuery.put(table, person).where(!Person.id.exists).execute
found <- DynamoDBQuery.get(table)(Person.id.partitionKey === "1").execute.absolve
_ <- DynamoDBQuery.update(table)(Person.id.partitionKey === "1")(
Person.name.set("Smith")
).execute
_ <- ZIO.debug(found == person) // true
} yield ()