Skip to content

Commit

Permalink
more hi level API
Browse files Browse the repository at this point in the history
  • Loading branch information
googley42 committed Oct 9, 2024
1 parent 0b700f3 commit d45f3b3
Showing 1 changed file with 44 additions and 3 deletions.
47 changes: 44 additions & 3 deletions docs/concepts/high-level-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,62 @@ title: "High Level API"
---

# High Level API
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.
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.

```scala
case class Person(id: String, name: String)
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.

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

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

## Using a `ProjectionExpression` as a springboards to creating further expressions

In the above example `Person.id` and `Person.name` are `ProjectionExpression`s 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

There are also type safe query creation methods in the DynamoDBQuery companion object such as `get`, `put`, `update`, `deleteFrom`, `queryAll` etc etc
## `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 query:

```scala
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
person <- DynamoDBQuery.get(table)(Person.id.partitionKey === "1").execute.absolve
_ <- DynamoDBQuery.update(table)(Person.id.partitionKey === "1")(
Person.name.set("Smith")
).execute
} yield ()
```

0 comments on commit d45f3b3

Please sign in to comment.