v0.17.0 : move of `smithy4s.api` shapes to `alloy` (and much more)
0.17.0
A word of warning
This Release is breaking on many levels and is therefore NOT compatible with the previous releases in any way : specifications / Scala sourcecode / binary code.
The most user-facing breakage is the move of smithy4s.api
smithy namespace to alloy
, as we've moved our definitions to a Scala-agnostic location. In theory, a project-wide string replacement of smithy4s.api
to alloy
should do the trick.
Read below for more information.
Abstract
This 0.17.0 release of Smithy4s brings a number of improvements on the abstractions implemented by the generated code, in particular in terms of flexibility and user experience.
This release also aims at bringing inter-operability with other tools and projects that Disney Streaming is putting forward to reinforce the Smithy ecosystem, such as smithy-translate and alloy.
In order to achieve these improvements, we've had to break a number of things at different levels. This release is therefore neither source nor binary compatible with the previous ones, and also forces the user to update their Smithy specifications.
Breaking changes
Smithy-level breaking changes
See #561
The Smithy shapes that were previously residing under smithy4s.api
namespace have moved to the alloy
namespace. Alloy is a standalone library containing Smithy shapes and validators, defined here.
The reason for us to bring this change is to have a language specific location to define shapes that are relevant to the protocols/runtime-behaviours we're putting forward, that could be used by tooling working with other languages than Scala. It was important for us to lose the 4s
suffix, which is short for for Scala
.
This change implies, for instance, that any use of smithy4s.api#simpleRestJson
in your specification will have to be replaced by alloy#simpleRestJson
.
Note that this change, in use cases that follow our documentation, should have no visible effect in the Scala code.
Build-plugins breaking changes (SBT/mill)
Multiple input directories
See #587
The smithy4sInputDir
setting/task in SBT/mill has been replaced by smithy4sInputDirs
, allowing the user to set several directories where the plugins should look for Smithy files.
Change in smithy-library dependency resolution
See #607
We've changed the smithy-sharing mechanism to do two things:
- By default, any dependency declared "normally" in SBT or mill, by means or
libraryDepedencies ++=
ordef ivyDeps
, will be inspected for Smithy files after being resolved. This means that, for instance, if your application has a runtime dependency on a library that was built with Smithy4s and contains Smithy files, your local specs can use the code defined in these Smithy files to create or annotate new shapes. You no longer need to declare those using% Smithy4s
ordef smithy4sIvyDeps
: these are now reserved for libraries containing Smithy files that you do not want your application's runtime to depend on. - Libraries built by Smithy4s automatically track the dependencies that they used during their own code-generation, by storing some metadata in their Jar's manifests. By default, the Smithy4s plugins will also pull those dependencies (which will have been declared upstream using
% Smithy4s
in SBT ordef smithy4sIvyDeps
in mill), for your project's code generation. This facilitates the transitivity of specification-holding artifacts. This mechanism is used, for instance, to communicate to users projects the fact that Smithy4s depends on shapes that are defined in the alloy library, and that these shapes should be made available to user projects, without impacting the user's application runtime, and without requiring any setup from the user.
Normal-usage breaking changes in the generated code
See #599
Depending on your setup, it may be a breaking change, but @deprecated
Smithy-traits now translate to the @deprectated
Scala annotation in the generated code. For instance, if you used @enum
heavily, you'll probably deprecation warnings in your console when compiling. Depending on your scalacOptions
, it is possible that these warnings turn into errors. If you want to silence these particular errors while upgrading, you can do the following:
scalacOptions ++= Seq(
"-Wconf:msg=object Enum in package api is deprecated:silent",
"-Wconf:msg=type Enum in package api is deprecated:silent",
// for Scala 3
"-Wconf:msg=object Enum in package smithy.api is deprecated:silent",
"-Wconf:msg=type Enum in package smithy.api is deprecated:silent"
)
Normal-usage source breaking changes
See #569
If you use Smithy4s in the ways that were previously advertised in the documentation, you may have to perform some small adjustments.
In particular, the simpleRestJson
extension method that was added to implementations of service-interfaces generated by Smithy4s is now removed, in favour of the SimpleRestJsonBuilder
construct (which now works for any service
Smithy shape that will have been annotated with alloy#simpleRestJson
).
Additionally, some methods that were deprecated in 0.16.x releases have been removed.
Advanced usage breaking changes
The abstractions that the generated code implements and that the runtime interpreters use have undergone some massive changes.
Non-exhaustive list of symbol renames :
old | new |
---|---|
smithy4s.Monadic | smithy4s.kinds.FunctorAlgebra |
smithy4s.Interpreter | smithy4s.kinds.FunctorInterpreter |
smithy4s.Service#asTransformation | toPolyFunction |
smithy4s.Service#transform | fromPolyFunction |
smithy4s.PolyFunction | smithy4s.kinds.PolyFunction |
smithy4s.Transformation | smithy4s.kinds.PolyFunction5 |
smithy4s.GenLift[F]#λ | smithy4s.kinds.Kind1[F]#toKind5 |
Unification of the natural-transformations/polymorphic functions.
- Smithy4s makes a lot of use of polymorphic functions of various kinds. Those are now code-generated (see the
project/Boilerplate.scala
file) to ensure the consistency of the various ways they are being used. This means thatsmithy4s.PolyFunction
has moved tosmithy4s.kinds.PolyFunction
, and that the previoussmithy4s.Transformation
is nowsmithy4s.kinds.PolyFunction5
. This decision ripples in thesmithy4s.Service
interface, which now sportstoPolyFunction
andfromPolyFunction
methods, allowing to turn a finally-encoded implementation into a final one.smithy4s.kinds.PolyFunction2
is also a thing, and may be used in bi-functor contexts. kind
-specific types were created to facilitate the "lift" of constructs to the right kinds. For instance, when inspecting the internals of this library, you might see things likeKind1[IO]#toKind5
where it was previouslyGenLift[IO]#λ
. We're hoping to convey meaning better, although this code is definitely still not trivial (and never will).smithy4s.Transformation
is now a typeclass-like construct, which expresses the fact that a construct can be applied like a function. This construct is used by thetransform
method that is generated on service interfaces, which allows to apply custom behaviour generically on all method invocations in these interfaces.- The
Service
interface takes a singleAlg
type parameter, theOp
parameter has moved to type-member position, facilitating implicit search in some contexts (as well as the writing of some logic). - A bunch of path-dependent type aliases were created in the
Service
interface. - The
compliancetest
module has changed drastically in UX. For those not aware, this module allows to run tests written in Smithy against your own implementation of protocols. This will be useful for third-party libraries that implementsimpleRestJson
(or any other http/rest like protocol), to virtually get tests for free. We don't think this module had any users so far, but we'll slowly be porting some of our tests away from thesmithy4s
repository and into thealloy
repository.
User facing improvements
Stubs
See #595
It is now possible to quickly stub a service with a default value (IO.stub
being a good candidate), which can be helpful for testing purposes. The resulting code looks like this :
import smithy4s.hello._
import cats.effect._
val stubbedHelloWorld : HelloWorldService[IO] = new HelloWorldService.Default[IO](IO.stub)
Transformations, including bi-functors
See #584
smithy4s.Transformation
has been revised to facilitate the integration with various shapes of transformations. It allows, in particular, to transform a service implementation by applying generic (but polymorphic) behaviour in all of its methods. For instance, this can be used to apply a timeout on all of the methods of a service, or retrying behaviour, etc ...
In particular, the smithy4s.Transformation
companion object contains in particular AbsorbError
and SurfaceError
interfaces that developers can leverage to get their services to go from mono-functor (where all errors are treated as Throwable
) to bi-functor (where errors are surfaced on a per-endpoint basis, forcing the developers to handle them one way or another), and vice-versa.
Bi-functor-specialised type aliases
The generated code now contains bi-functor-specialised ErrorAware
type-aliases. Those, combined with the transformations described above, should make it easier to interop with Bi-functor constructs such as EitherT
or ZIO
.
Endpoint Specific Middleware
See #614
Adds the ability to have smithy4s-level middleware that is made aware of the Server
and Endpoint
for use in creating middleware implementations. This unlocks creating middleware that is aware of the Smithy traits (Hints
in smithy4s) and shapes in your specification. This means the middleware can apply transformations based on traits applied in a Smithy specification and it can return error responses defined in the Smithy specification. An example of this is authentication. You are now able to create middleware that will check authentication on only the endpoints that require it AND you can return a smithy-defined error response when the authentication is not valid. See the endpoint specific middleware guide for more.
Error Response Handling Improvements
See #570
Streamlines and improves how error responses are mapped to their corresponding smithy4s-generated types. It now works such that IF no X-Error-Type
header is found AND the status code doesn't map precisely to an error annotated with @httpCode
AND exactly one error happens to have @error("client")
without @httpCode
, that error will be selected (provided the status code is in the 4xx range). Same for @error("server")
and 5xx range. See the error handling documentation for more.
Support for more HTTP methods
Previously, smithy4s's HttpEndpoint
was limited to supporting just a small subset of HTTP methods (POST
, GET
, PATCH
, PUT
and DELETE
). This is now mitigated, and all other methods are accepted by HttpEndpoint
, by means of an open-enumeration.
Configurable maximum arity during Json parsing
See #569
In order to mitigate known security problems, our json parsing logic has hard-limits over the number of elements it will parse from arrays
or maps, resulting in an error when receiving payloads with larger collections. Previously, this limit was hardcoded to 1024 elements per collection. This is now configurable, 1024 being the default.
Polymorphic refinements
See #649
Refinements applied on list/map shapes can now produce parameterised types. This allows, for instance, to have generic
refinements on list
shapes that produce cats.data.NonEmptyList
containing the same types of elements.
What's Changed
- main into series/0.17 by @kubukoz in #560
- Polyfunction revamp by @Baccata in #555
- Migrate smithy4s.api -> alloy by @lewisjkl in #561
- Update smithy-aws-traits, smithy-build, ... to 1.26.0 by @scala-steward in #554
- [series/0.17] fix CI trigger (and build) by @Baccata in #573
- add get default method by @lewisjkl in #580
- Add Alt dispatch projector by @lewisjkl in #582
- Move Op from parameter to member in smithy4s.Service by @Baccata in #567
- Error handling improvements by @lewisjkl in #570
- Support more HTTP methods, keep more details about HTTP matching failures by @kubukoz in #493
- Use get default func by @lewisjkl in #588
- [0.17] Remove/hide deprecated symbols by @kubukoz in #589
- Merge main into 0.17 by @kubukoz in #583
- Add error-related transformations + documentation by @Baccata in #584
- Dynamic generated sources by @lewisjkl in #598
- Support multiple input dirs (sbt, mill) by @lewisjkl in #587
- Fix to send empty body, and consume it by @daddykotex in #522
- Render "Default" classes that can be used to stub an implementation by @Baccata in #595
- allow passing in the MaxArity for the JsonSchemaVisitor by @yisraelU in #569
- Render deprecation hints by @kubukoz in #599
- Add Default to default codec hintMask by @kubukoz in #618
- Implement HttpProtocolCompliance w/o IO by @daddykotex in #613
- Drop IO also in the implicit CompatEffect summon by @daddykotex in #624
- Endpoint-Specific Middleware by @lewisjkl in #614
- Add a dependency tracking mechanism by @Baccata in #607
- Add a message when no files are generated by @daddykotex in #627
- 0.17 main sync by @Baccata in #628
- Refine compliance tests dx by @Baccata in #623
- smithy4sInputDirs more conservative default by @lewisjkl in #630
- Fix a NPE when calling getAttributes on a null manifest by @daddykotex in #634
- Bump alloy-core by @daddykotex in #629
- Update sbt-sonatype to 3.9.15 by @scala-steward in #638
- Update nscplugin, sbt-scala-native, ... to 0.4.9 by @scala-steward in #637
- Revise some type aliases / add path-dependent ones by @Baccata in #639
- Update smithy-aws-traits, smithy-build, ... to 1.26.4 by @scala-steward in #640
- Unifies resolution before codegen by @Baccata in #646
- Define source/resource generator together by @daddykotex in #643
- Document the assembly rule by @daddykotex in #650
- Polymorphic refinements by @lewisjkl in #649
- Docusaurus updates by @daddykotex in #566
- Clean-up the codegen module to have a very small API surface by @Baccata in #648
- remove dependency on test-utils from complianceTests by @yisraelU in #652
- AWS: expose detailed errors in AwsClient.prepare by @kubukoz in #619
- Remove duplicate Transformation trait by @kubukoz in #653
- Remove the Service.Provider construct by @Baccata in #654
- Sync 0.17 with main by @Baccata in #655
- 0.17.0 Changelog draft [skip ci] by @Baccata in #631
Full Changelog: v0.16.10...v0.17.0