-
-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Map ctx.request.params to corresponding method parameters #507
Comments
Thank you for suggesting this issue @OrkhanAlikhanov . I had many issues in previous coding experiences when managing method parameters based on names. They are supposed to be dummy variables and are often treated as is during compilation or code minifying, causing the app to fail. From what I understand, the point here would be not to write every the time the whole
index(@Param('id') id: number) {
// ...
} This would solve the naming issue but I'd rather not to go with a heavy usage of decorators (which is often a criticize of Nest). I'm moving this to |
Well, we can make it completely minification proof if we pass params in order. We can infer param names from path ( @Get('/:id/:name/:value')
index(ctx, myId, myName, myValue) {
return ...
} What do you think? |
Interesting. This would solve the naming issue indeed. But in this case, Foal will have to manually parse the path This may also generate conflicts in large apps with many sub-controllers (see example below). @Get('/users/:userId')
class UserController {
@Post('/friends/:friendId')
deleteUserRelationShip(ctx, friendId) {
// Is it `friendId` or `userId`?
}
} Maybe we could also pass the @Get('/:id/:name/:value')
index(ctx, { id, name, value }) { // equivalent to index(ctx, params)
// do something with the variables "id", "name" and "value".
return ...
} @Get('/users/:userId')
class UserController {
@Post('/friends/:friendId')
deleteUserRelationShip(ctx, { friendId }) { // or { friendId, userId }
...
}
} |
Amazing idea! That eliminates lots of maintenance and reliability headache |
The class ProductController {
@Get('/products')
@ValidateQueryParam(...)
@ValidateQueryParam(...)
findProducts(ctx, params, { from, to }) {
...
}
} |
It would be great to have a config file to configure order of those params. Kindof a js config file where we can define a method to return array of method arguments to be passed to controller functions, defaulting to [ctx, ctx.request.params, ctx.request.query, ctx.request.body] |
I think having a class ProductsController {
transformCtxToParams(ctx) {
return [ctx, ctx.request.params, ctx.request.query]
}
@Get('/products')
@ValidateQueryParam(...)
@ValidateQueryParam(...)
async findProducts(ctx, params, { from, to }) {
...
}
} I think inheritance should not affect in this case and the array returned from class AppController {
subControllers = [
ProductsController /// uses its own transformCtxToParams
],
transformCtxToParams(ctx) {
return [null]; /// does not affect subControllers
}
} Alternatively a metadata on const MyParamMapper = Hook(ctx => {
/// foal uses value of `methodParams` in calling endpoint methods.
ctx.state.foal.methodParams = [ctx, ctx.request.params, ctx.request.query];
});
@MyParamMapper
class ProductsController {
@Get('/products')
@ValidateQueryParam(...)
@ValidateQueryParam(...)
async findProducts(ctx, params, { from, to }) {
...
}
} This way applying the hook on a parent controller would affect entire children. Just sharing ideas came to my mind. |
following up on my comment on #490: The issue is basically with the current design of FoalTS encourages type-unsafe access of context properties. Let's describe this using an example taken from the docs: import { Contains, Length } from 'class-validator';
export class SocialPost {
@Length(10, 20)
title: string;
@Contains('hello')
text: string;
} import { Context, HttpResponseCreated, Post } from '@foal/core';
import { ValidateBody } from '@foal/typestack';
import { SocialPost } from './social-post.validator';
export class SocialPostController {
@Post()
@ValidateBody(SocialPost)
createSocialPost(ctx: Context) {
const body = ctx.request.body;
// do something with the body
return new HttpResponseCreated();
}
} In the example above This means I can accidentally type stuff like:
Normally I would expect the
In other frameworks this is usually solved more elegantly by having parameter decorator, i.e.: export class SocialPostController {
@Post()
createSocialPost(@ValidateBody(SocialPost) body: SocialPost) {
// do something with the body
return new HttpResponseCreated();
}
} I'm aware I could do
Imo the nicest way I've seen this solved is in plumier: |
Feature implemented in v1.9. |
It would be great if we could map
ctx.request.params
to same named method arguments:It would be better if we could map them irrespective of order, based on names.
The text was updated successfully, but these errors were encountered: