Open aryairani opened 9 years ago
The primary use of shapeless in rho is for the HList
type signatures. Honestly it wouldn't be too hard to just make a phantom type that can be consed like a HList
and use a normal List[Any]
for the storage, but shapeless is a transient dependency of rho so why not use it?
TypedPath
holds the 'phantom' HList
type signature and stores the path AST nodes untyped. It is known by the HList
type signature what order parameters will be produced by the path and therefor they are safe to cast to whatever they need to be. The other typed ASTs (query etc..) work the same way.
The power of the HList
phantom type comes to bear when making an action using a RouteExecutable
(many of the action building type extend this so long as they have enough information to meaningfully match a request). Here the phantom type is used to typecheck the function used to build the action. In this process you need a CompileService
in scope to get anything useful. A CompileService
can generate documentation, make a actual route etc.
That should get you started.
Side question: what is an action, the part after the |>>
, or the whole thing?
GET / "puppy" / "bySSN" / pathVar[SSN] |>> { owner: SSN => Ok(Puppy.cutest.filter(_.lovingOwner === owner).asJson) }
Edit: and what is this expression even doing to cause the service to remember it?
The whole thing. A RhoAction
just holds all the bits of the path definition, the function F
used to execute it (or whatever fits the HListToFunc
paired with it: F
could be a Task[Response]
or even a constant that has a EntityEncoder
), and the 'converter' which is the HListToFunc
. In turn the HListToFunc
must find a ResultMatcher
which is where some of the 'status code' magic happens, but its primary purpose is take the Request
and whatever the result of the function F
(or whatever it is) and convert that to a Task[Response]
to be shipped back to the client.
If you look at the type signature of |>>
you'll notice that it takes an implicit CompileService
which will receive the final RhoAction
and can then do whatever it likes with it. The CompileService
can be stateful and save the route (in the typical case, a route tree for matching against a request), but it doesn't have to be. For example it could simply compile it into a Request => Task[Response]]
and you get to do what you want with it, or it could generate some documentation (swagger!), whatever you like.
P.S. Get it? The distant island kingdom is the UK.
Is there more than one CompileService
? I could only find one, in RhoService
, so I'm probably looking for the wrong thing. If one wanted to create a new output format, what would the critical format-specific pieces be?
Wait, I guess the critical piece is overriding RhoService#append
.
"Papa, where do
TypedPaths
come from?" "Well, that story starts a long time ago, in a distant island kingdom..."