Skip to content

Releases: arainko/ducktape

ducktape 0.2.6

22 Oct 06:25
eb6844d
Compare
Choose a tag to compare

This is a bugfix release that fixes a compiletime issue where the wrong owners were used for a lambda in fallible accumulating transformations which sometimes manifested itself in an error after macro expansion.

It also fixes a runtime issue that resulted in an exception being thrown when directly configuring coproduct cases with Field configs.

What's Changed

Full Changelog: v0.2.5...v0.2.6

ducktape 0.2.5

31 Aug 06:21
ec336e5
Compare
Choose a tag to compare

This release removes a limitation of transformation configs that disallowed using them like lenses for updates, eg. the following:

case class Person(age: Int, name: String)

Person(1, "Joe").into[Person].transform(Field.const(_.age, 23))

would previously fail to compile because the transformation underneath was an identity transformation (i.e. not a configurable product-to-product transformation) - this has now been lifted and code like the above now works as you'd expect.

What's Changed

Full Changelog: v0.2.4...v0.2.5

ducktape 0.2.4

29 Jul 20:04
ba40550
Compare
Choose a tag to compare

ducktape 0.2.4

This a bugfix release.

Special-cased Option transformations shouldn't get dropped when doing fallible transformations with a Mode[Option] in scope.

Additionally, match-type-based tuple transformations are now bulletproof to most of the quirks of match types so stuff like tuple concatenation shouldn't throw it off.

What's Changed

  • Tuple docs by @arainko in #184
  • Update sbt-typelevel-ci-release, ... to 0.7.2 by @scala-steward in #186
  • Make Context.current a transparent inline to make it work under Scala 3.4.+ by @WojciechMazur in #189
  • [Issues #187 and #190] Make F-unwrapping not interfere with special-cased Option transformations and make transformations more bulletproof in relation to match types by @arainko in #191

Full Changelog: v0.2.3...v0.2.4

ducktape 0.2.3

15 Jul 20:54
54d7942
Compare
Choose a tag to compare

ducktape 0.2.3

This release brings the ability to transform tuples in all kind of ways (tuple-to-tuple, product-to-tuple, tuple-to-product), so stuff like this is now possible:

import io.github.arainko.ducktape.*

case class Source(field1: Int, field2: List[Int], field3: Int, field4: Int)

Source(1, List(2, 2, 2), 3, 4).to[(Int, Vector[Int], Option[Int])]
// res18: Tuple3[Int, Vector[Int], Option[Int]] = (
//   1,
//   Vector(2, 2, 2),
//   Some(value = 3)
// )

(1, List(2, 2, 2), 3, 4).to[Source]
// res19: Source = Source(
//  field1 = 1,
//  field2 = List(2, 2, 2),
//  field3 = 3,
//  field4 = 4
// )

The newly added ability for F-unwrapping (i.e. lifting the wrapper type into the 'outside' of a fallible transformation) in conjuction with tuple transformation enables some fantastic use cases for match types, like the ability to 'traverse' a tuple:

import io.github.arainko.ducktape.*

val source =
  (
    Right(1),
    Right("str"),
    Right(List(3, 3, 3)),
    Right(4)
  )

Mode.Accumulating.either[String, List].locally {
  source.fallibleTo[Tuple.InverseMap[source.type, Mode.current.Self]]
}
// res0: Either[List[String], *:[Int, *:[String, *:[List[Int], *:[Int, EmptyTuple]]]]] = Right(
//   value = (1, "str", List(3, 3, 3), 4)
// )

...which is really just the tip of the iceberg - stay tuned for a more in-depth look on how this mechanism can be leveraged in other use cases.

Head on over to the docs on configuring tuples to see how the configuration DSL works with tuples.

What's Changed

Full Changelog: v0.2.2...v0.2.3

ducktape 0.2.2

27 May 20:28
b889101
Compare
Choose a tag to compare

This release brings back lints for configs that override each other, for example:

final case class FieldSource(additionalArg: String, str: String)

val fieldSource = FieldSource("str-sourced", "str2")

val expected = TestClassWithAdditionalString(1, "str2", "str-computed")

testClass
    .into[TestClassWithAdditionalString]
    .transform(
        Field.allMatching(fieldSource),
        Field.allMatching(fieldSource),
      )

will result in a compilation warning that looks like this:

Configs for:
  * TestClassWithAdditionalString.str
  * TestClassWithAdditionalString.additionalArg
are being overriden by Field.allMatching(fieldSource) @ AppliedBuilderSuite.scala:185:41

It also introduces Mode#locally that allows you to use a Mode in a scope of a function so that it doesn't need to be bound to a given.

What's Changed

Full Changelog: v0.2.1...v0.2.2

ducktape 0.2.1

19 May 10:31
e726035
Compare
Choose a tag to compare

This release adds a lint that rejects calls to non-Transformer.define* family of methods in given Transformer declarations (#165 )

What's Changed

Full Changelog: v0.2.0...v0.2.1

ducktape 0.2.0

28 Mar 20:57
c2823f8
Compare
Choose a tag to compare

ducktape 0.2.0

First of all, head on over to the new docs site.

The library has been rebuilt from the ground-up to not rely on automatic derivation of Transformer and Transformer.Fallible and enable further development of more advanced features (the examples of which are nested configurations and support for regional configs like Field.fallbackToDefault - with more still to come). All of that should result in a much higher quality of code that gets generated underneath (for example, fallible transformations do not generate interim Transformer.Fallible instances anymore).

While this release is not binary-compatible with ducktape 0.1.x, it's aiming to be as source-compatible as possible. All the known breakages are documented in the Coming from 0.1.x section of the docs. There are also a bunch of deprecated forwarders with (hopefully) user-friendly tips on how to make the deprecation warnings go away.

New highlight features

  • ability to configure deeply nested transformations without having to resort to building out new Transformer instances, best showcased in the Configuring transformations section of the docs

  • revamped error reporting - errors are now accumulated and shown at once and are supposed to be actionable e.g. in case of a field that's missing it'll give the user a hint and a path to that field for usage in one of the configuration options, for example:

    No field 'name' found in MdocApp0.this.wire.PaymentMethod.Card @ Person.paymentMethods.element.at[MdocApp0.this.domain.Payment.Card].name
    

    More information is available in the Motivating example section of the docs.

  • new flavor of configuration options - regional configs:

    • Field.fallbackToDefault for falling back to default values in cases where a transformation couldn't be derived,
    • Field.fallbackToNone for falling back to None for Option fields for which a transformation couldn't be derived
      Regional configs can be made to work in only user-selected subregions of the transformations, eg.:
    Field.fallbackToDefault.regional(_.field1.at[Case1])

    will make it apply only 'below' field1 at it's Case1 subtype. More info and examples are available in Configuring transformations

What's Changed

Full Changelog: v0.2.0-RC1...v0.2.0

ducktape 0.2.0-RC1

22 Mar 18:18
ecebb3a
Compare
Choose a tag to compare

ducktape 0.2.0-RC1

The first release candidate of the 0.2.x line - to be promoted to a final 0.2.0 release if nothing comes up in the next week.
Starting from this release the default branch will start pointing to the series/0.2.x branch.

The docs are now published on a docs page as opposed to being kept in a readme.

What's Changed

Full Changelog: v0.2.0-M5...v0.2.0-RC1

ducktape 0.2.0-M5

10 Mar 15:24
9560997
Compare
Choose a tag to compare

ducktape 0.2.0-M5

This release bring a new encoding of accumulating transformations (well, the 'decoding', really) - the final step destructing the zipped Tuple is now represented as a chain of accessors, i.e. this:

 (value: Tuple2[Type, Tuple2[Type, Type]]) => new Person(name = value._1, age = value._2._1, socialSecurityNo = value._2._2)
  ): Either[List[String], Person]): Either[List[String], Person])

instead of a pattern match like this one:

value: Tuple2[Tuple2[Type, Type], Type]) =>
              value match {
                case Tuple2(Tuple2(name, age), socialSecurityNo) =>
                  new ValidatedPerson(name = name, age = age, socialSecurityNo = socialSecurityNo)
                case x =>
                  throw new MatchError(x)
              }
          )

This release is very likely to become an RC if nothing serious comes up in the next week.

What's Changed

Full Changelog: v0.2.0-M4...v0.2.0-M5

ducktape 0.2.0-M4

24 Feb 13:16
13272b8
Compare
Choose a tag to compare

This release is identical to 0.2.0-M3 in terms of features. Publishing should be fixed now.

What's Changed

  • remove tooling, inline Debug, fix publishing by @arainko in #123

Full Changelog: v0.2.0-M3...v0.2.0-M4