xsc
released this
Assets
2
I'm very proud to announce the latest release of claro, a library to streamline your data access, providing powerful optimisations and abstractions along the way.
Check out the Basic Resolution guide or the Quickstart README section for an introduction!
Infinity ...
This release sees claro's increased support for infinite trees, causing a significant shift in focus. We move away from inline transformations that wrap a Resolvable and are run once a concrete value is available – instead, we can now rely on an abstract description on how to convert an infinite tree to a finite one, a so-called projection.
Previously, similar to muse or urania, we built an abstract resolvable tree, inlining transformation logic close to the affected nodes:
(-> (->Person 1)
(data/then
(fn [person]
(-> person
(select-keys [:id :name :friends])
(update :friends #(data/map :name %))))))Considering claro supports infinite trees we have to be very careful to only apply the transformation once all necessary data is available – but, then again, we can't wait for a value to be fully resolved since we don't have any guarantees that that'll ever happen. This resulted in the introduction of conditional composition, guarding transformations with predicates asserting the shape of a subtree before function application.
Needless to say, there were surprises and extended README sections on what to especially look out for. We can do better.
Consider the following projection which'll do the same thing as the piece of code above:
(def person-with-friend-names
{:id projection/leaf
:name projection/leaf
:friends [(projection/extract :name)]})
(-> (->Person 1)
(projection/apply person-with-friend-names))Projections are queries and schemas at once. They are declarative, composable and powerful, and they'll let you cleanly separate external transformation logic from your data access (which can now seamlessly produce dumb, rich, infinite trees). Moreover, together with claro's improved mocking capabilities projections are independently testable.
All in all, I firmly believe that this is a big step forward. If you agree, disagree or just want to chat don't hesitate to open an issue or contact me on Twitter.
To infinity!
... and Beyond!
The idea of projections is heavily inspired by GraphQL. It seems thus only natural that there should be a GraphQL layer on top of claro – which I expect to be a rather straightforward endeavour, seeing as projections are a superset of GraphQL queries.
If you're also interested in this – or have ideas/drive/code towards a concrete implementation – feel free to contact me. This is, in my opinion, the next logical step.
Release Notes
Auto-Generated Documentation | Guides
Breaking Changes
- data manipulation functions have been moved out of
claro.dataintoclaro.data.ops, wrap-selecthas been removed – use selectors instead,wrap-resolvehas been removed – usewrapinstead,- the
overrideandoverridesmiddlewares have been removed – use the ones inclaro.middleware.mockinstead, - the
traceandtrace-statsmiddlewares have been removed – use the ones inclaro.middleware.observeinstead.
Features
resolve-batch!can now either return an in-order seq of results or a map of resolvable/result pairs,claro.data/Transformhas been added to separate pure and impure resolvable logic,- new projections & capabilities:
alias: renames a key,bind/let: uses a partial result to generate the actual projection,case: dispatches on theResolvabletype,conditional: dispatches on a partialResolvableresult,default/maybe: replaces or acceptsnilvalues,extract: reads a leaf value from a subtree,parameters: injects values intoResolvablerecords,prepare: transformsResolvablerecords before resolution,transform: transformsResolvableresults,union/conditional-union: merges projection results,value: injects concrete values (which, themselves, can beResolvablerecords).
- better error messages for projections,
- introduces adapters (
claro.engine.adapter), - introduces selectors (
claro.engine.selector), allowing stateful resolution strategies, - adds middlewares:
claro.middleware.observe: engine introspection middlewares,claro.middleware.transform: resolution result transformation middlewares,claro.middleware.mock: data source mocking middlewares,claro.middleware.deferred: deferred value transformation middlewares.
Artifact Coordinates
[claro "0.2.0]