Closed kwhitley closed 1 year ago
Test coverage at the moment...
So I think by overloading the createResponse()
helper (that creates json
, error
, etc), I can ditch the respondWithJSON
and just pass json
in at the end. I'm hoping same for responseWithError
(in favor of just error
).
This would allow the end handler to share the familiar helpers:
// CF ES6 module syntax
export default {
fetch: (request: IRequest, env: object, context: object) =>
router
.handle(request, env, context)
.then(json)
.catch(respondWithError) // this could just become .catch(error)
.then(corsify)
}
add downstream handler support to existing Response creators to further streamline individual route code
Would be cool if the downstream handler could be provided a copy of the request, so that, for instance, a cleanup function could be run before returning. In my case, I need to do a context.waitUntil()
to log out of an API, using an API client that I add on to request.
Closed with the release of v4 :)
Proposed/TODO
error
- pass this to the.catch()
functionjson
/etc - pass this to a.then()
afterrouter.handle
to transform unformed data into a Responseroute
intorequest.route
for determining route catch from within handlersTypes
Let me get this out there... types in itty are HARD. First, it's a Proxy, which are not very type-friendly to begin with. Next, we want ALL the flexibility (to serve all the various audiences), and that's where the problems really begin. We could, for instance, pass generics at a router level, to define Request type, additional args, etc. This works great, and a single set of types can serve an entire router.
But what if you want to override just a particular route? For example, use a UserRequest on a route that has a
withUser
middleware upstream. This no longer works.Conversely, you can do the opposite, and allow full, per-route customization. It's more verbose to be sure, but it allows you to define what you want, where you want it - the tradeoff being that you have to define them more often.
Ultimately, this is the path I'm leaning towards. There's nothing more frustrating than fighting types - including boilerplate (as much as I obviously hate that). With that in mind, here are the proposed type changes:
Changes
IRequest
will now be a union onRequest
(Web Standard), to allow type hinting on the Request object. This is overdue.<RequestType, Args>
though, as that is the signature I'd ultimately like to pass down, if we can ever achieve that.IRequestStrict
, which is just likeIRequest
, but without the generic traps to allow any undeclared variable. Want to lock down a route? Define a custom Request type based onIRequestStrict
instead ofIRequest
.Each route can use custom Request types and args either via typed params, or generics.
Usage Example
In the example below, note the lack of manual
new Response()
or evenjson(data)
creation. By including a single downstream handler at the outermost/root router, we can let routes return Responses, raw data, or even Promises to raw data/Responses (e.g. a request to a database). Downstream, we can wrap everything in a Response if not already formed :)Update
Rather than include a separate handler (
respondWithJSON
/respondWithError
), I've overloaded the existing function signatures to ignore Requests/Responses. This allows them to be used as global post-route handlers (as well).