/claim #519 /closes #519
Both Scala 2 and Scala 3 have compile time validation. They extract the ShapeTree of SchemaA and SchemaB, and do a Tree.diff which returns added and removed, of the form List[List[Segement]]
private[migration] object Segment {
case class Field(name: String) extends Segment
case class Case(name: String) extends Segment
case object Element extends Segment
case object Key extends Segment
case object Value extends Segment
case object Wrapped extends Segment
}
When .build is run, as we go through MigrationAction, each migration action collects Handled and Provided, which is also of the form List[List[Segement], which are then compared against added and removed. On success we compile.
Example of List[List[Segement]: List(Field("address"), Field("city")) -> It has one single path address.city
Note - This is a different List of Lists, rather than encoding level and field. I though having a clear path to the field which was added or removed was a better decision.
_.address.street + _.address.city → _.address.fullAddress -> this is done
_.address.street + _.origin.country → _.address.fullAddress -> This gets complex since now we have to extract values from multiple nested source paths, combine to targeted nested path, remove the nested source fields, and rebuilt the whole structure immutability.
So if the parent is not the same, it gracefully errors out at both runtime (if .buildpartial was used) and during compile validation (if .build was used)
DynamicMigration is Pure ADT and can be inspected structurally, but it cannot be fully serialize/deserialize it due to existential types in SchemaExpr. SchemaExpr[DynamicValue, ?], not sure how to deal with this.
Ajay RV
@Nanashi-lab
ZIO
@ZIO