Search code examples
javascriptnode.jstypescriptnestjsrouteparams

How to get nested URL query in Nest.js


I have NestJS application I have to get the query from the URL. Problem is that my creationDate is an object and I can't get it as the nested object via @Query.

Here is example of the route:

xxx/yyy/orders?key1=value&key2=value&key3=value&createdAt[lte]=2021-07-01&createdAt[gte]=2011-03-30&orderBy=desc&limit=500

I am trying to get createdAt[lte] and createdAt[gte] as the nested object

export interface QueryI {
key1: string;
key2: string;
key3: string;
key4: string;
createdAt: {
    lte: string,
    gte: string,
}
orderBy: 'desc' | 'asc';
limit: number;
}

Here is my controller:

@Get('route')
getAll(
    @Query() query: QueryI): Promise<void> { 
    return this.myService.findAll(query);
}

but this gives me following result

{

key1: 'value',        
  key2: 'value',
  key3: 'value',       
  key4: 'value',
  'createdAt[lte]': 'some date',
  'createdAt[gte]': 'some date',
  orderBy: 'desc',
  limit: '500'

}

I have tried JSON.stringify and consulted similar questions on SOW but no luck.

Thank you


Solution

  • EDIT

    In the end I have implemented diferent classes and used @Pipe to validate my query: Here is the code:

    pipe.ts

    @Injectable()
    export class ValidateQueryPipe implements PipeTransform {
      transform(value: any, metadata: ArgumentMetadata) {
        let incomingQuery = value as IncomingQuery;
        let mappedQuery = new QueryParameters()
        mappedQuery.key1 = incomingQuery.key1
        mappedQuery.key2= incomingQuery.key2
        // other mapped valus
        mappedQuery.createdAt = new CreatedAt(incomingQuery['createdAt[lte]'], incomingQuery['createdAt[gte]'])        
        return mappedQuery;
      }
    

    controller.ts

    @Get(':someurl/someurl')
    getAllOrders(
        @Query(ValidateQueryPipe) query: QueryParameters): Promise<Observable<any>> { 
        return this.service.findAll(erpCode, query);
    }
    

    query-parameters.ts

    import { CreatedAt } from "./created-at";
    
    export class QueryParameters {
        key1: string;
        key2: string;
        createdAt: CreatedAt;
    }
    

    created-at.ts

    export class CreatedAt {
        lte: string;
        gte: string;
    
        constructor(lte: string, gte: string){
            this.lte = lte;
            this.gte = gte;
        };
    }
    

    Well I have found a partial solution and I will post it here untill better answer comes along: I am extracting the nested properties into seperate queries and creating my model. It's not perfect but it's doing the job for now...

    controller.ts

     getAllOrders(
        @Query() query,
        @Query('createdAt[lte]') lte: string, 
        @Query('createdAt[gte]') gte: string): Promise<void> { 
        const mappedObject = new QueryParameters(query, lte, gte)
        return this.orderService.findAll(erpCode, mappedObject);
    }
    

    createdAtModel.ts

        export class CreatedAt {
        lte: string;
        gte: string;
    
        constructor(lte: string, gte: string){
            this.lte = lte;
            this.gte = gte;
        };
    }
    

    my-model.ts

    import { CreatedAt } from "./created-at";
    
    export class QueryParameters {
        //other keys
        createdAt: CreatedAt;
    
        constructor(query, lte, gte){
            //other keys
            this.createdAt = new CreatedAt(lte, gte)
        }
    }
    

    I am sure that better answer lies in using the NestJS validation pipes but I didn't manage to find the one that works for me.