Best way to add helper methods to context object in Koa2 - node.js

I would like to add method such as view and json to the context object passed to my controllers. I do this in a middleware that runs before everything else:
async function(ctx, next){
ctx.view = view.bind(ctx);
ctx.json = json.bind(ctx);
await next()
ctx.renderer.render();
}
these methods set some conventional configuration object (Renderer) that the middleware interprets and then renders out the actual response by setting the correct ctx.body. That allows me to switch template language easily and have an easier time combining API and Template requests.
Except it doesn't work because after await next() the ctx.renderer is the default one, not the one set by controllers. I suspect it's a namespacing issue, but I am not sure where it comes from.
What's the best practice to attach functions to the context that can reference context without it being passed to them?

Ok it's here in the docs I just missed it, the docs are inside a repo and are not hosted, which makes them hard to navigate.
TL;DR: use app.context to access the context prototype. Adding functions there attaches them to the context object and allows you to use this from within to access it.

Related

Typescript change type of the Request after checkAuth middleware

I'm pretty new to typescript and I faced the issue with extending the Request type. I actually found a solution, but it doesn't feel right to me, and seems like there might be a better way.
First, the structure. I have a middleware checkAuth that checks the Bearer token, finds the user in the database (or creates one, in case it's the first time) and adds user to the req variable.
Most people recommend modifying the Express' Request type with custom declarations. I don't like this idea, because that will put user object into all requests, even before I actually save user into req.
Another solution is what I use now:
interface ReqWithUser extends Request {
user?: {
...
}
}
This allows me to declare req: ReqWithUser. But there's a flaw. When I try to access req.user, typescript is telling me that it's possibly undefined. Well, that's exactly what I declared with user?:. If I don't put a question mark there, then typescript is mad in router, saying Property 'user' is missing in type Request. That's fair. One of the solution is to use req!.user. Solves all problems, but it still feels imperfect to me. I know the req.user is there, it's not optional, otherwise checkAuth would fail and return 401. If it didn't, the user is there. What feels like the right solution is somehow modify the req type after the checkAuth middleware. Because that's when user is added into the req. Is it possible?
The issue has nothing to do with your types, but it's the fact that Express will always emit Request and not RequestWithUser.
So in your middleware function, you will always get a Request. The only reason RequestWithUser is acceptable is because you made it optional.
Truth is the middleware / decorator pattern doesn't work that well with express. You have a few options (some of which you mentioned)
Use declaration merging to 'patch' the built-in Request. You already mentioned you don't like this though, because it's a bit of a hack.
Don't use Express' middleware system and instead write something that understands how types change with decorators. I don't know exactly what this looks like, or if this has been done before.
Whenever you want to use RequestWithUser in your controllers/middlewares start off with an assertion function to ensure that user exists (allowing you to make it non-optional).
Cast to RequestWithUser, when you need it.
All these options have drawbacks:
You don't like for the reasons mentioned. It's not always 'accurate' so you are sort of lying to Typescript for convenience.
Sounds hard to do
Requires the use of an assertion function, which means you need to do a little extra work every time you want to use the user property. This work is not needed because you as developer know.
You probably don't like casting for the same reason you don't like to use declaration merging.
By far I think 2 is the best solution, because it gives you the advantage of typing without any hacks and without having to do the extra work of an assertion function (which happens during runtime). But it means abandoning Express' Middleware system. I wouldn't know exactly how to write this code, but I am curious how if it can be done...
FYI I opened another stack overflow question, because I am curious:
Typescript typing for decorator middleware patterns

Build a validation parameter decorator in typescript

I read the doc, been there, done that. Still no clue how to write a decorator I need in a way that makes common sense.
In brief: Got an interceptor that executes before the validation layer. That simply means that invalid data can get in the interceptor and break the app. To avoid that I would like to use a decorator on some methods, and to be more accurate on parameters of such methods.
public async getUserById(#IsIntNumber() userId: number): Promise<UserEntity>
{
// method logic
}
Here #IsIntNumber() is a custom decorator that validates the userId parameter.
As a matter of fact I'd like to have a little library of mine in the application holding a bunch a that kinds of validation decorators that I could apply to different parameters.
Is there some legal method to do this without shedding too much blood and too many tears?
I know it's a difficult question.
In the docs they sort of say:
The #required decorator adds a metadata entry that marks the parameter
as required. The #validate decorator then wraps the existing greet
method in a function that validates the arguments before invoking the
original method.
Meaning I've got to pack all my validation logic into that validate function or what? Really?
Does it mean that we don't have adequate parameter decorators in TS? Cos if I understand this right, these ones are absolutely, totally unusable.

Using Custom Functions with "I" in Page Object and Custom Helper in CodeceptJS

Hi CodeceptJS Community,
Is there a way to use custom defined functions (under steps_file.js) as I. customFunction() in page object files.
Is there a way to use native codeceptjs functions (like I.click()) in my custom helper files
I couldn't find any help in the documentation and in other sources. Is there any way to achieve this?
And is there any way to use xpath locators in puppeteer helper?
this.helpers['Puppeteer'].page.click(xpath);
I had the same problem to use custom steps in pageObjects.
To avoid it, i passed the actor (I) as parameter to my pageObject function.
page object:
const I = actor();
module.exports = {
doSomething(I){
I.login();
}
};
Test scenario:
Scenario('Test something' (I,pageObject)=>{
pageObject.doSomething(I)
})
In this case, pageObjects will has access to all custom steps from I :)
Thank you for your sharing Matheus. I have used a different solution. Instead of writing "I" object in every page object method (which was also one option for me), I have created a custom helper file and written all methods using puppeteer helper like below;
async method() {
await this.helpers['Puppeteer'].click(xpath);
}
I can call this method both in tests and page objects
I.method();
I was facing the same issue and when I looked into the typescripts definitions I noticed that actor() which is required in every page object etc. has custom steps arguments.
So this worked for me to extend the const I = actor(); witht the custom steps form steps_file.js;
const customSteps = require('./steps_file');
const I = actor(customSteps());
After that, I can use all methods in page objects like in tests scenarios which are accessing the methods from steps_file.js

Problems de-serializing System.Security.Claims.Claim

I'm implementing an oAuth server and need to store refresh tokens, to do this I have (at the moment) chosen to serialize the tokens into JSON.
While I can see that the JSON includes everything that would be needed to rehydrate, when I de-serialize with token.FromJson() the embedded claims are not being reconstructed correctly.
So far I've considered inheriting from JsonConverter to create a claims converter but don't see a way of adjusting the global JsConfig to utilise it :(
Can any one point me in a good direction?
So...
Walking away from the code and returning did the trick!
Instead of using a JsonConverter you need to utilise a generic version of JsConfig when changing/overriding the behaviour of ServiceStack on a specific class, just stick the following in your services start-up code for example.
JsConfig<Claim>.SerializeFn = claim => string.Format("{0}|{1}", claim.Type, claim.Value);
JsConfig<Claim>.DeSerializeFn = claimDetails =>
{
var values = claimDetails.Split('|');
return new Claim(values[0], values[1]);
};

Should an instance of a JsonServiceClient be wrapped into a using statement?

Is it a best practice to wrap the ServiceStack's JsonServiceClient within a using statement?
var client = new JsonServiceClient();
client.Post(request);
versus
using (var client = new JsonServiceClient())
{
client.Post(request);
}
Which one is the best?
JsonServiceClient implements IDisposable so best practise would be to use it with a using statement.
However there are scenarios whereby you need to the share an instance of the JsonServiceClient across multiple requests (Such as when you use cookie based sessions, as the cookies are contained in the instances cookie container), in which case you would use the client without a using statement, but ensure that your application calls the Dispose method of the client, when it no longer requires the client.
This answer by gdoron further explains the best practise regarding classes that implement IDisposable such as the JsonServiceClient and the reasoning behind it.
As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):
I hope that helps.

Resources