1111// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212// See the License for the specific language governing permissions and
1313// limitations under the License.
14- import { Request , Response , NextFunction , Express } from 'express' ;
14+ import { Express } from 'express' ;
1515import { HandlerFunction } from '../functions' ;
1616import { ILayer } from 'express-serve-static-core' ;
1717
@@ -31,72 +31,74 @@ const COMMON_EXPRESS_OBJECT_PROPERTIES = [
3131/** The number of parameters on an express error handler. */
3232const EXPRESS_ERROR_HANDLE_PARAM_LENGTH = 4 ;
3333
34- /** A express app error handle. */
35- interface ErrorHandle {
36- // eslint-disable-next-line @typescript-eslint/no-explicit-any
37- ( err : Error , req : Request , res : Response , next : NextFunction ) : any ;
38- }
39-
4034/**
41- * Express middleware to propagate framework errors to the user function error handle.
42- * This enables users to handle framework errors that would otherwise be handled by the
43- * default Express error handle. If the user function doesn't have an error handle,
44- * it falls back to the default Express error handle.
35+ * Injects the user function error handle middleware and its subsequent middleware
36+ * chain into the framework. This enables users to handle framework errors that would
37+ * otherwise be handled by the default Express error handle.
38+ * @param frameworkApp - Framework app
4539 * @param userFunction - User handler function
4640 */
47- export const createPropagateErrorToClientErrorHandleMiddleware = (
41+ export const injectUserFunctionErrorHandleMiddlewareChain = (
42+ frameworkApp : Express ,
4843 userFunction : HandlerFunction
49- ) : ErrorHandle => {
50- const userFunctionErrorHandle =
51- getFirstUserFunctionErrorHandleMiddleware ( userFunction ) ;
44+ ) => {
45+ // Check if user function is an express app that can register middleware.
46+ if ( ! isExpressApp ( userFunction ) ) {
47+ return ;
48+ }
49+
50+ // Get the index of the user's first error handle middleware.
51+ const firstErrorHandleMiddlewareIndex =
52+ getFirstUserFunctionErrorHandleMiddlewareIndex ( userFunction ) ;
53+ if ( ! firstErrorHandleMiddlewareIndex ) {
54+ return ;
55+ }
5256
53- return function (
54- err : Error ,
55- req : Request ,
56- res : Response ,
57- next : NextFunction
57+ // Inject their error handle middleware chain into the framework app.
58+ const middlewares = ( userFunction as Express ) . _router . stack ;
59+ for (
60+ let index = firstErrorHandleMiddlewareIndex ;
61+ index < middlewares . length ;
62+ index ++
5863 ) {
59- // Propagate error to user function error handle.
60- if ( userFunctionErrorHandle ) {
61- return userFunctionErrorHandle ( err , req , res , next ) ;
64+ const middleware = middlewares [ index ] ;
65+
66+ // We don't care about routes.
67+ if ( middleware . route ) {
68+ continue ;
6269 }
6370
64- // Propagate error to default Express error handle.
65- return next ( ) ;
66- } ;
71+ frameworkApp . use ( middleware . handle ) ;
72+ }
6773} ;
6874
6975/**
70- * Returns the first user handler function defined error handle, if available .
71- * @param userFunction - User handler function
76+ * Returns if the user function contains common properties of an Express app .
77+ * @param userFunction
7278 */
73- const getFirstUserFunctionErrorHandleMiddleware = (
74- userFunction : HandlerFunction
75- ) : ErrorHandle | null => {
76- if ( ! isExpressApp ( userFunction ) ) {
77- return null ;
78- }
79+ const isExpressApp = ( userFunction : HandlerFunction ) : boolean => {
80+ const userFunctionProperties = Object . getOwnPropertyNames ( userFunction ) ;
81+ return COMMON_EXPRESS_OBJECT_PROPERTIES . every ( prop =>
82+ userFunctionProperties . includes ( prop )
83+ ) ;
84+ } ;
7985
86+ /**
87+ * Returns the index of the first error handle middleware in the user function.
88+ */
89+ const getFirstUserFunctionErrorHandleMiddlewareIndex = (
90+ userFunction : HandlerFunction
91+ ) : number | null => {
8092 const middlewares : ILayer [ ] = ( userFunction as Express ) . _router . stack ;
81- for ( const middleware of middlewares ) {
93+ for ( let index = 0 ; index < middlewares . length ; index ++ ) {
94+ const middleware = middlewares [ index ] ;
8295 if (
8396 middleware . handle &&
8497 middleware . handle . length === EXPRESS_ERROR_HANDLE_PARAM_LENGTH
8598 ) {
86- return middleware . handle as unknown as ErrorHandle ;
99+ return index ;
87100 }
88101 }
89102
90103 return null ;
91104} ;
92-
93- /**
94- * Returns if the user function contains common properties of an Express app.
95- * @param userFunction
96- */
97- const isExpressApp = ( userFunction : HandlerFunction ) : boolean => {
98- const userFunctionProperties = Object . getOwnPropertyNames ( userFunction ) ;
99- return COMMON_EXPRESS_OBJECT_PROPERTIES . every ( prop =>
100- userFunctionProperties . includes ( prop )
101- ) ;
102- } ;
0 commit comments