@@ -72,7 +72,7 @@ interface ParamDefinition {
7272 /** Parameter position in method signature */
7373 index : number ;
7474 /** Type of parameter (query, body, etc.) */
75- type : 'query' | 'param' | 'body' | 'req' | 'res' | 'logger' | 'reqHeader' ;
75+ type : 'query' | 'param' | 'body' | 'req' | 'res' | 'logger' | 'reqHeader' | 'reqId' | 'cookie' ;
7676 /** Optional key for extracting specific property */
7777 key ?: string ;
7878 /** Optional ParamOptions for advanced extraction */
@@ -504,7 +504,7 @@ export function Use(...middlewares: RequestHandler[]): MethodDecorator & ClassDe
504504 */
505505export interface ParamOptions < T = any > {
506506 /** Base type of the parameter (default: 'string') */
507- type : 'string' | 'number' | 'boolean' ;
507+ type ? : 'string' | 'number' | 'boolean' ;
508508
509509 /** Data structure type (default: 'single') */
510510 dataType ?: 'single' | 'array' | 'object' ;
@@ -540,14 +540,36 @@ export interface ParamOptions<T = any> {
540540 transform ?: ( value : any ) => any ;
541541}
542542
543- function createParamDecorator ( type : ParamDefinition [ 'type' ] , key ?: string ) {
543+ function defineParamMetadata (
544+ target : any ,
545+ propertyKey : string | symbol ,
546+ parameterIndex : number ,
547+ type : ParamDefinition [ 'type' ] ,
548+ key : string | undefined
549+ ) {
550+ const params : ParamDefinition [ ] = Reflect . getMetadata ( PARAMS_KEY , target , propertyKey ) || [ ] ;
551+
552+ params . push ( { index : parameterIndex , type, key } ) ;
553+ params . sort ( ( a , b ) => a . index - b . index ) ;
554+
555+ Reflect . defineMetadata ( PARAMS_KEY , params , target , propertyKey ) ;
556+ }
557+
558+ export function createParamDecorator (
559+ type : ParamDefinition [ 'type' ] ,
560+ key ?: string
561+ ) : ( paramKey ?: string ) => ParameterDecorator {
544562 return ( paramKey ?: string ) : ParameterDecorator => {
545563 return ( target , propertyKey , parameterIndex ) => {
546- const params : ParamDefinition [ ] = Reflect . getMetadata ( PARAMS_KEY , target as object , propertyKey as string ) || [ ] ;
547- // Ensure parameters are ordered by index
548- params . push ( { index : parameterIndex , type, key : paramKey || key } ) ;
549- params . sort ( ( a , b ) => a . index - b . index ) ;
550- Reflect . defineMetadata ( PARAMS_KEY , params , target as object , propertyKey as string ) ;
564+ defineParamMetadata ( target , propertyKey as string , parameterIndex , type , paramKey ?? key ) ;
565+ } ;
566+ } ;
567+ }
568+
569+ export function createParamDecoratorWithoutParam ( type : ParamDefinition [ 'type' ] ) : ( ) => ParameterDecorator {
570+ return ( ) : ParameterDecorator => {
571+ return ( target , propertyKey , parameterIndex ) => {
572+ defineParamMetadata ( target , propertyKey as string , parameterIndex , type , undefined ) ;
551573 } ;
552574 } ;
553575}
@@ -652,7 +674,21 @@ export const Body = createParamDecorator('body');
652674 * }
653675 * ```
654676 */
655- export const ReqLogger = createParamDecorator ( 'logger' ) ;
677+ export const ReqLogger = createParamDecoratorWithoutParam ( 'logger' ) ;
678+
679+ /**
680+ * Decorator that extracts request ID from headers.
681+ * @returns Parameter decorator
682+ *
683+ * @example
684+ * ```ts
685+ * @Get ('/data')
686+ * getData(@ReqId() reqId: string) {
687+ * // reqId will contain the value of req.headers['x-request-id'] or req.id
688+ * }
689+ * ```
690+ */
691+ export const ReqId = createParamDecoratorWithoutParam ( 'reqId' ) ;
656692
657693/**
658694 * Decorator that extracts request headers.
@@ -669,6 +705,21 @@ export const ReqLogger = createParamDecorator('logger');
669705 */
670706export const ReqHeader = createParamDecorator ( 'reqHeader' ) ;
671707
708+ /**
709+ * Decorator that extracts cookies from request.
710+ * @param key - Optional key to extract specific cookie
711+ * @returns Parameter decorator
712+ *
713+ * @example
714+ * ```ts
715+ * @Get ('/data')
716+ * getData(@ReqCookie('session_id') sessionId: string) {
717+ * // sessionId will contain the value of req.cookies['session_id']
718+ * }
719+ * ```
720+ */
721+ export const ReqCookie = createParamDecorator ( 'cookie' ) ;
722+
672723/**
673724 * Decorator that injects the entire request object.
674725 *
@@ -683,7 +734,7 @@ export const ReqHeader = createParamDecorator('reqHeader');
683734 * }
684735 * ```
685736 */
686- export const Req = createParamDecorator ( 'req' ) ;
737+ export const Req = createParamDecoratorWithoutParam ( 'req' ) ;
687738
688739/**
689740 * Decorator that injects the response object.
@@ -699,7 +750,7 @@ export const Req = createParamDecorator('req');
699750 * }
700751 * ```
701752 */
702- export const Res = createParamDecorator ( 'res' ) ;
753+ export const Res = createParamDecoratorWithoutParam ( 'res' ) ;
703754
704755/**
705756 * Decorator that sets a custom HTTP status code for a response.
@@ -1387,6 +1438,12 @@ export function registerControllers(router: Router, controllers: any[]) {
13871438 case 'reqHeader' :
13881439 args [ index ] = key ? req . headers [ key . toLowerCase ( ) ] : req . headers ;
13891440 break ;
1441+ case 'reqId' :
1442+ args [ index ] = req . headers [ 'x-request-id' ] || req ?. id || undefined ;
1443+ break ;
1444+ case 'cookie' :
1445+ args [ index ] = key ? req . cookies ?. [ key ] : req . cookies ;
1446+ break ;
13901447 }
13911448 } ) ;
13921449 }
@@ -1529,7 +1586,7 @@ function applyParamOptions(rawValue: any, options: ParamOptions, key?: string) {
15291586
15301587 // Apply type conversion to each array element
15311588 if ( options . type ) {
1532- value = value . map ( ( v : any ) => convertType ( v , options . type ) ) ;
1589+ value = value . map ( ( v : any ) => convertType ( v , options . type || 'string' ) ) ;
15331590 }
15341591 } else if ( options . dataType === 'object' ) {
15351592 // Handle object data type
0 commit comments