Building Chainable Middleware with the Builder Pattern
This exercise is a real mind-bender, but it showcases the power of generics and the builder pattern.
We start with a
DynamicMiddleware class which lets you create a chain of inputs and outputs, and then run them to get a result.
DynamicMiddleware takes in a function as an argument. This function takes in an input and returns an output.
0:00 This exercise is a real mind-bender and shows off some of the power of generics and the power of this builder pattern. We have a dynamic middleware class. This dynamic middleware class basically lets you create a chain of inputs and outputs, which then allows you to run them and spit out a result.
0:19 The dynamic middleware, the first time you call it, it takes in a function, which takes in an input and returns an output. What you can see here is this middleware type has middleware TInput, TOutput, input, input, and then returns this. It's a function that returns either TOutput or a promise wrapping TOutput.
0:42 Then we can see in the constructor, we're taking the first middleware. The dynamic middleware class infers that type from. What you can see is when we call this, we have request locked in in the first type argument. In the second type argument, I promise you it's a request but it also has a user ID added to it.
1:06 If we remove that user ID, then we end up with request and this thing. If we just return the request, then it infers request, request. If we return a number, it infers a number. You can pass anything to it and do any transformations to it. The issue is this use function is not quite delivering.
1:26 There's one more thing to show you, which is, at the end, what you should be able to do is you should be able to return middleware.run and await it, and then you end up with the result. The result should be what gets returned from the last use that's been called. Currently, the flow is we've got a request here. We append a user ID to it.
1:48 We check if the user ID has a...if it's 123, then for some reason that's a bad idea. We don't want that user ID. We throw an error. Otherwise, we do one more transformation where we take the request and we add a user to it where we fetch the user. This fetch user is just coming from a fake external library. It's just like returning some data.
2:11 That's coming from fake external lib. You don't need to touch this. You don't need to worry about fetch user. The only bits you're going to need to change are inside this function. There are a few as anys here that you are going to need because we're doing some really highly generic complicated stuff here.
2:29 These anys, too, also, you're probably going to need them. Now, the issue here is that it doesn't seem to be picking up the fact that this seems to be just another request inside here. It seems like when we add the use, we're going to need to infer some generics there when we call the use because we're going to need to infer the thing that's being passed back from this.
2:55 Nothing seems to be working here. Your job is we're probably going to need to add an extra generic onto use. We're probably going to need to think about this slightly differently and definitely change this return type because currently this is just typed as any here. We're going to need to add something in this slot here.
3:19 There's a lot there. Think about what you've seen from the builder pattern before and how you need to change the top-level generic or maybe alter it in some way. We're definitely going to need to return dynamic middleware in some sense because we're just returning this after having mutated it. A lot there. See if you can get your brain in gear. Good luck.