@@ -40,16 +40,20 @@ describe('Class: BaseRouter', () => {
4040 }
4141 }
4242
43- public async resolve ( event : unknown , context : Context ) : Promise < unknown > {
43+ public async resolve (
44+ event : unknown ,
45+ context : Context ,
46+ options ?: any
47+ ) : Promise < unknown > {
4448 this . #isEvent( event ) ;
4549 const { method, path } = event ;
4650 const route = this . routeRegistry . resolve ( method , path ) ;
4751 try {
4852 if ( route == null )
4953 throw new NotFoundError ( `Route ${ method } ${ path } not found` ) ;
50- return route . handler ( event , context ) ;
54+ return await route . handler ( event , context ) ;
5155 } catch ( error ) {
52- return await this . handleError ( error as Error ) ;
56+ return await this . handleError ( error as Error , options ) ;
5357 }
5458 }
5559 }
@@ -590,4 +594,180 @@ describe('Class: BaseRouter', () => {
590594 expect ( result . headers . get ( 'Content-Type' ) ) . toBe ( 'application/json' ) ;
591595 } ) ;
592596 } ) ;
597+
598+ describe ( 'decorators error handling' , ( ) => {
599+ it ( 'works with errorHandler decorator' , async ( ) => {
600+ // Prepare
601+ const app = new TestResolver ( ) ;
602+
603+ class Lambda {
604+ @app . errorHandler ( BadRequestError )
605+ public async handleBadRequest ( error : BadRequestError ) {
606+ return {
607+ statusCode : HttpErrorCodes . BAD_REQUEST ,
608+ error : 'Bad Request' ,
609+ message : `Decorated: ${ error . message } ` ,
610+ } ;
611+ }
612+
613+ @app . get ( '/test' )
614+ public async getTest ( ) {
615+ throw new BadRequestError ( 'test error' ) ;
616+ }
617+
618+ public async handler ( event : unknown , context : Context ) {
619+ return app . resolve ( event , context ) ;
620+ }
621+ }
622+
623+ const lambda = new Lambda ( ) ;
624+
625+ // Act
626+ const result = ( await lambda . handler (
627+ { path : '/test' , method : 'GET' } ,
628+ context
629+ ) ) as Response ;
630+
631+ // Assess
632+ expect ( result ) . toBeInstanceOf ( Response ) ;
633+ expect ( result . status ) . toBe ( HttpErrorCodes . BAD_REQUEST ) ;
634+ expect ( await result . text ( ) ) . toBe (
635+ JSON . stringify ( {
636+ statusCode : HttpErrorCodes . BAD_REQUEST ,
637+ error : 'Bad Request' ,
638+ message : 'Decorated: test error' ,
639+ } )
640+ ) ;
641+ } ) ;
642+
643+ it ( 'works with notFound decorator' , async ( ) => {
644+ // Prepare
645+ const app = new TestResolver ( ) ;
646+
647+ class Lambda {
648+ @app . notFound ( )
649+ public async handleNotFound ( error : NotFoundError ) {
650+ return {
651+ statusCode : HttpErrorCodes . NOT_FOUND ,
652+ error : 'Not Found' ,
653+ message : `Decorated: ${ error . message } ` ,
654+ } ;
655+ }
656+
657+ public async handler ( event : unknown , context : Context ) {
658+ return app . resolve ( event , context ) ;
659+ }
660+ }
661+
662+ const lambda = new Lambda ( ) ;
663+
664+ // Act
665+ const result = ( await lambda . handler (
666+ { path : '/nonexistent' , method : 'GET' } ,
667+ context
668+ ) ) as Response ;
669+
670+ // Assess
671+ expect ( result ) . toBeInstanceOf ( Response ) ;
672+ expect ( result . status ) . toBe ( HttpErrorCodes . NOT_FOUND ) ;
673+ expect ( await result . text ( ) ) . toBe (
674+ JSON . stringify ( {
675+ statusCode : HttpErrorCodes . NOT_FOUND ,
676+ error : 'Not Found' ,
677+ message : 'Decorated: Route GET /nonexistent not found' ,
678+ } )
679+ ) ;
680+ } ) ;
681+
682+ it ( 'works with methodNotAllowed decorator' , async ( ) => {
683+ // Prepare
684+ const app = new TestResolver ( ) ;
685+
686+ class Lambda {
687+ @app . methodNotAllowed ( )
688+ public async handleMethodNotAllowed ( error : MethodNotAllowedError ) {
689+ return {
690+ statusCode : HttpErrorCodes . METHOD_NOT_ALLOWED ,
691+ error : 'Method Not Allowed' ,
692+ message : `Decorated: ${ error . message } ` ,
693+ } ;
694+ }
695+
696+ @app . get ( '/test' )
697+ public async getTest ( ) {
698+ throw new MethodNotAllowedError ( 'POST not allowed' ) ;
699+ }
700+
701+ public async handler ( event : unknown , context : Context ) {
702+ return app . resolve ( event , context ) ;
703+ }
704+ }
705+
706+ const lambda = new Lambda ( ) ;
707+
708+ // Act
709+ const result = ( await lambda . handler (
710+ { path : '/test' , method : 'GET' } ,
711+ context
712+ ) ) as Response ;
713+
714+ // Assess
715+ expect ( result ) . toBeInstanceOf ( Response ) ;
716+ expect ( result . status ) . toBe ( HttpErrorCodes . METHOD_NOT_ALLOWED ) ;
717+ expect ( await result . text ( ) ) . toBe (
718+ JSON . stringify ( {
719+ statusCode : HttpErrorCodes . METHOD_NOT_ALLOWED ,
720+ error : 'Method Not Allowed' ,
721+ message : 'Decorated: POST not allowed' ,
722+ } )
723+ ) ;
724+ } ) ;
725+
726+ it ( 'preserves scope when using error handler decorators' , async ( ) => {
727+ // Prepare
728+ const app = new TestResolver ( ) ;
729+
730+ class Lambda {
731+ public scope = 'scoped' ;
732+
733+ @app . errorHandler ( BadRequestError )
734+ public async handleBadRequest ( error : BadRequestError ) {
735+ return {
736+ statusCode : HttpErrorCodes . BAD_REQUEST ,
737+ error : 'Bad Request' ,
738+ message : `${ this . scope } : ${ error . message } ` ,
739+ } ;
740+ }
741+
742+ @app . get ( '/test' )
743+ public async getTest ( ) {
744+ throw new BadRequestError ( 'test error' ) ;
745+ }
746+
747+ public async handler ( event : unknown , context : Context ) {
748+ return app . resolve ( event , context , { scope : this } ) ;
749+ }
750+ }
751+
752+ const lambda = new Lambda ( ) ;
753+ const handler = lambda . handler . bind ( lambda ) ;
754+
755+ // Act
756+ const result = ( await handler (
757+ { path : '/test' , method : 'GET' } ,
758+ context
759+ ) ) as Response ;
760+
761+ // Assess
762+ expect ( result ) . toBeInstanceOf ( Response ) ;
763+ expect ( result . status ) . toBe ( HttpErrorCodes . BAD_REQUEST ) ;
764+ expect ( await result . text ( ) ) . toBe (
765+ JSON . stringify ( {
766+ statusCode : HttpErrorCodes . BAD_REQUEST ,
767+ error : 'Bad Request' ,
768+ message : 'scoped: test error' ,
769+ } )
770+ ) ;
771+ } ) ;
772+ } ) ;
593773} ) ;
0 commit comments