NestJSX get parameter from CrudRequest object - nestjs

I want to overrride the following route which was generated by nestjsx:
GET /offer-event-matchings/{id}
To get the id from the CrudRequest I wrote the following code.
#Override()
getOne(#ParsedRequest() req: CrudRequest): Promise<GetUserDto> {
const id = req.parsed.search.$and[1]['id']['$eq'];
return this.service.getOfferEventMatching(id);
}
It works but I think and hope there is a better and more beautiful way to get the id from the CrudRequest object?

The bottom of the section Routes Override in the docs mentions you can use the typical decorators as well, so the easiest would be to use Param:
getOne(
#ParsedRequest() req: CrudRequest,
#Param('id') id: string
): Promise<GetUserDto> {
// code here
}

Related

How to get gql return type of resolver from within resolver?

EDIT: Maybe a simpler question - Is there any way of accessing __typename in a resolver? like this php question https://github.com/webonyx/graphql-php/discussions/1087
I am trying to prevent manually defining the type arg of fieldWasRequested below. Can I reliably get this string from within the resolver? This would be the same as the resolvers __typename value. I found a way that kinda gets close but is ultimately too brittle.
I am using parseResolveInfo from graphql-parse-resolve-info to check if a field was requested in a resolver. In order to do this, I need to access the type name of the resolver. Currently I am manually setting this and getting the name by looking at the graphql schema file.
import { parseResolveInfo } from 'graphql-parse-resolve-info'
export const fieldWasRequested = (field: string, type: string, info: GraphQLResolveInfo) => {
const parsedInfo = parseResolveInfo(info)
const fields = parsedInfo?.fieldsByTypeName?.[type] ?? {}
return field in fields
}
export const thing1: Resolvers['thing1'] = async (parent, args, ctx, info): Promise<Thing1[]> => {
const fieldWasRequested = fieldWasRequested('field1', 'Thing1', info)
// continued ...
}
I see there is info.returnType, which is this GraphQLOutputType. This is a unioin of many types, all of which seem to have a toString method.
Logging info.returnType.toString() returns [Thing1]. This is an array of Thing1. But for other resolvers it could be Thing2, [Thing3!]!, etc. It's just not feasible to parse from this. Is there a better way?

Can I write a DTO which extracts both query and params vars in nestjs

I'm making an api which looks like:
http://example.com/story/:storyId/analytics?from={date}&to={date}
The storyId is part of the path, but from and to are query parameters.
I've got a DTO, like this:
class GetStoryAnalyticsDTO {
storyId: string
from: Date
to: Date
}
(validators omitted for brevity)
And I'm using it like this in my controler:
#Get()
getStoryAnalytics(#Query() query: GetStoryAnalyticsRequestDto): Promise<MyResponse> {...}
But, (obviously!), this only extracts the from and to parameters.
Is there any way to extract both from the query and the path to get all the vars in one dto?
If not, it's not a massive hassle - I can just add #Param storyId: string to the controller and it's all good :)
You could make a custom decorator like #QueryParam() that pulls together req.query and req.params. It could look something like this:
export const QueryParam = createParamDecorator((data: unknown, context: ExecutionContext) => {
const req = context.switchToHttp().getRequest();
return { ...req.query, ...req.params };
});
And just make sure to add validateCustomDecorators on the ValidationPipe if you want it to auto validate for you. Otherwise, you're good to start using it.

Does nestjs support Get and Post simultaneously on an action?

I am new to nestjs and tring to apply Get and Post simultaneously on a method in my controller.
For simplicity, I just post the core logic code snippet:
Customized Decorator
import { Get, Post } from "#nestjs/common";
import { RenderReact } from 'my-personal-package';
export function Page(path: string, view?: React.ComponentType, methodDecorators?: ((path?: string | string[]) => MethodDecorator)[]): MethodDecorator {
return (target: any, key: string, desc: PropertyDescriptor) => {
const decorators = [
Get(path), // Add Get first.
Post(path) // Add Post then.
];
if (view) {
decorators.push(RenderReact(view)); // RenderReact will return a MethodDecorator as well.
}
decorators.forEach(decorate => decorate(target, key, desc));
return desc;
};
}
Controller method:
#Page("my-path", ThisIsMyPageFunctionalComponent, [Post]) // Post was from #nestjs/common
async return() {
// method logic
}
The array "decorators" at the very beginning in the Page function,
Add Get, then Post, Only Post works.
Add Post, then Get, Only Get works.
How can we apply Get/Post simultaneously here?
As #Micael Levi mentioned above, as the machanism of how decorator factory works, we can not apply both Get and Post in this way. I have tried it for a long time.
Please refer to the question here, like #Kim Kern posted
We extracted common logic into a method.
Separate the method Get and Post which will call the common logic.

How to use regexp for validate in nestjs?

I want to use regexp in validation in nestjs.
For example:
RegExp
pagePattern = '[a-z0-9\-]+';
Method
#Get('/:article')
getIndex(
#Param('article')
) {
}
What can I use?
ValidationPipe?
I would create a DTO class like
class ArticleParamDTO {
#Matches('[a-z0-9\-]+') // comes from class-validator
article: string;
}
And then you can use it in the route handler like
#Get(':article')
getIndex(#Param() { article }: ArticleParamDto) {
}
And then as long as you use the ValidationPipe it will all work. Anything that doesn't match will cause a 400 BadRequest

how to use optional url parameters with NestjS

I'm trying to replace our current backend service using Nestjs library,
however, I want to create a route with 2 optional parameters in the URL something like :
/route/:param1/config/:OptionalParam3?/:OptionalParam3?
that means the route should catch :
route/aa/config
route/aa/config/bb
route/aa/config/bb/cc
how can I achieve that, I have tried to use ? and () but it's not working well.
If you are looking for how to annotate an optional query parameter, you can do it like so:
#ApiQuery({
name: "myParam",
type: String,
description: "A parameter. Optional",
required: false
})
async myEndpoint(
#Query("myParam") myParam?: string
): Promise<blah> {
[...]
}
Router params name should be unique. The correct route path is:
Existing one is:
/route/:param1/config/:OptionalParam3?/:OptionalParam3?
Correction:
/route/:param1/config/:OptionalParam3?/:OptionalParam4?
Opinion: You can use query params if the params are optional. It is never a good idea to create optional param routes (disagreements agreed). Both serve the same purpose, but having them as the query params makes it more understandable for debugging and fellow developers.
I solved this problem by using #Query decorator as below:
Here is my controller:
#Get()
async getAll(#Query('someParameter') someParameter?: number) {
return this.service.getAll(someParameter);
}
Here is my client (Angular) service:
getAll(someParameter?: number) {
return this.http.get(`apiUrl/controllerAddress?someParameter=${someParameter}`
);
}
You can use this structure:
-route
-aa
-config
-[[...id]].js
It will work for the routes :
route/aa/config/{anything}

Resources