@morojs/moro 1.8.4 → 1.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/core/utilities/hooks.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,cAAc,EAAE,gBAAgB;IAChC,aAAa,EAAE,eAAe;IAC9B,eAAe,EAAE,iBAAiB;IAClC,cAAc,EAAE,gBAAgB;IAChC,KAAK,EAAE,OAAO;CACN,CAAC;AAEX,MAAM,OAAO,WAAY,SAAQ,YAAY;IACnC,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC1C,WAAW,GAAG,IAAI,GAAG,EAA0B,CAAC;IAChD,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC/C,MAAM,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAEhD,2BAA2B;IAC3B,4DAA4D;IACpD,YAAY,GAAG,IAAI,GAAG,EAA0D,CAAC;IAEzF,2DAA2D;IACnD,cAAc,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEpD,8EAA8E;IAC9E,gFAAgF;IACxE,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAEzC;QACE,KAAK,EAAE,CAAC;QACR,yBAAyB;QACzB,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,KAAK,KAAK,SAAS;gBAAE,SAAS;YAClC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC1B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAChC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC/B,iCAAiC;YACjC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,8CAA8C;IACtC,kBAAkB,CAAC,KAAa;QACtC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAEpD,qDAAqD;QACrD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9E,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;YACtE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,sBAAsB;YAC5D,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAE7B,sCAAsC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QACzE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAExC,IAAI,OAAO,EAAE,CAAC;YACZ,8DAA8D;YAC9D,mDAAmD;YACnD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,OAAoB,EAAE,EAAE;gBACrD,qCAAqC;gBACrC,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC;gBACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;oBACnC,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;wBAC5B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;4BACvB,IAAI,CAAC,OAAO,CAAC,CAAC;wBAChB,CAAC;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,yEAAyE;wBACzE,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;wBAC5E,MAAM,cAAc,GAClB,YAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBAE1E,IAAI,cAAc,EAAE,CAAC;4BACnB,8EAA8E;4BAC9E,oDAAoD;4BACpD,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,sDAAsD,EACtD,eAAe,EACf;gCACE,KAAK,EAAE,YAAY;gCACnB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,SAAS;6BAC9C,CACF,CAAC;4BACF,SAAS;wBACX,CAAC;wBAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,eAAe,EAAE;4BACzD,KAAK,EAAE,YAAY;yBACpB,CAAC,CAAC;wBACH,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;gBAED,mCAAmC;gBACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;oBAClC,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;wBACtB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;4BACvB,IAAI,CAAC,OAAO,CAAC,CAAC;wBAChB,CAAC;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,yEAAyE;wBACzE,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;wBAC5E,MAAM,cAAc,GAClB,YAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBAE1E,IAAI,cAAc,EAAE,CAAC;4BACnB,8EAA8E;4BAC9E,oDAAoD;4BACpD,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,sDAAsD,EACtD,eAAe,EACf;gCACE,KAAK,EAAE,YAAY;gCACnB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,SAAS;6BAC9C,CACF,CAAC;4BACF,SAAS;wBACX,CAAC;wBAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,eAAe,EAAE;4BACzD,KAAK,EAAE,YAAY;yBACpB,CAAC,CAAC;wBACH,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;gBAED,oCAAoC;gBACpC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC;gBACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;oBAClC,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;wBAC3B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;4BACvB,IAAI,CAAC,OAAO,CAAC,CAAC;wBAChB,CAAC;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,yEAAyE;wBACzE,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;wBAC5E,MAAM,cAAc,GAClB,YAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBAE1E,IAAI,cAAc,EAAE,CAAC;4BACnB,8EAA8E;4BAC9E,oDAAoD;4BACpD,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,sDAAsD,EACtD,eAAe,EACf;gCACE,KAAK,EAAE,YAAY;gCACnB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,SAAS;6BAC9C,CACF,CAAC;4BACF,SAAS;wBACX,CAAC;wBAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,eAAe,EAAE;4BACzD,KAAK,EAAE,YAAY;yBACpB,CAAC,CAAC;wBACH,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;gBAED,2BAA2B;gBAC3B,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAE1B,OAAO,OAAc,CAAC,CAAC,iCAAiC;YAC1D,CAAC,CAAQ,CAAC,CAAC;QACb,CAAC;aAAM,CAAC;YACN,gDAAgD;YAChD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAoB,EAAE,EAAE;gBAC1D,uBAAuB;gBACvB,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC;gBACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;oBACnC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;oBAC5B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;wBACvB,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC;gBAED,qBAAqB;gBACrB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;oBAClC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBACtB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;wBACvB,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC;gBAED,sBAAsB;gBACtB,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC;gBACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;oBAClC,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;oBAC3B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;wBACvB,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC;gBAED,2BAA2B;gBAC3B,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAE1B,OAAO,OAAO,CAAC;YACjB,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,kEAAkE;IAC1D,mBAAmB,CAAC,GAAG,UAA4B;QACzD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,kDAAkD;gBAClD,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;oBAC9C,OAAO,KAAK,CAAC;gBACf,CAAC;gBACD,8DAA8D;gBAC9D,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;oBAC9E,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,CAAC,gCAAgC;IAC/C,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,KAAa,EAAE,EAAgB;QAClC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5B,CAAC;QACD,oEAAoE;QACpE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yBAAyB;IACzB,MAAM,CAAC,KAAa,EAAE,EAAgB;QACpC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClC,CAAC;QACD,oEAAoE;QACpE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yBAAyB;IACzB,KAAK,CAAC,KAAa,EAAE,EAAgB;QACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,oEAAoE;QACpE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yEAAyE;IACzE,kEAAkE;IAClE,6EAA6E;IAC7E,uDAAuD;IACvD,QAAQ,CAAC,KAAa;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvE,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,OAAO,CAAC,KAAa,EAAE,UAAuB,EAAE;QACpD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QAED,0EAA0E;QAC1E,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC/B,oEAAoE;QACpE,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,4CAA4C;IACpC,KAAK,CAAC,WAAW,CAAC,IAAkB,EAAE,OAAoB;QAChE,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yEAAyE;YACzE,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,MAAM,cAAc,GAClB,YAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE1E,IAAI,cAAc,EAAE,CAAC;gBACnB,8EAA8E;gBAC9E,oDAAoD;gBACpD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,EAAE,eAAe,EAAE;oBACzF,KAAK,EAAE,YAAY;oBACnB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,SAAS;iBAC9C,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,+CAA+C;YAC/C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,eAAe,EAAE;gBACzD,KAAK,EAAE,YAAY;gBACnB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,SAAS;aAC9C,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,eAAe;IACf,UAAU,CAAC,KAAa,EAAE,EAAiB;QACzC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;YAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;gBACjC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBACpB,IAAI,GAAG,KAAK,SAAS;oBAAE,SAAS;gBAChC,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC7B,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBAChC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;wBACjB,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yCAAyC;IACzC,QAAQ,CAAC,KAAc;QACrB,IAAI,KAAK,EAAE,CAAC;YACV,OAAO;gBACL,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;gBACzC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;gBACjC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;aACxC,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAwB,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;YACxB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YACpB,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;YAC1B,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;SAC1B,CAAC,CAAC;QAEH,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACxB,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF","sourcesContent":["// Hook System for Moro\nimport { EventEmitter } from 'events';\nimport { HookFunction, HookContext } from '../../types/hooks.js';\nimport { createFrameworkLogger } from '../logger/index.js';\n\nexport const HOOK_EVENTS = {\n BEFORE_REQUEST: 'before:request',\n AFTER_REQUEST: 'after:request',\n BEFORE_RESPONSE: 'before:response',\n AFTER_RESPONSE: 'after:response',\n ERROR: 'error',\n} as const;\n\nexport class HookManager extends EventEmitter {\n private hooks = new Map<string, HookFunction[]>();\n private beforeHooks = new Map<string, HookFunction[]>();\n private afterHooks = new Map<string, HookFunction[]>();\n private logger = createFrameworkLogger('Hooks');\n\n // Cached execute functions\n // When no hooks are registered, replace execute() with noop\n private executeCache = new Map<string, (context: HookContext) => Promise<HookContext>>();\n\n // Track if hooks are synchronous to avoid Promise overhead\n private hookSyncStatus = new Map<string, boolean>();\n\n // Events that currently have at least one hook registered - lets callers skip\n // execute() entirely (no context object, no promise) when nothing is registered\n private activeEvents = new Set<string>();\n\n constructor() {\n super();\n // Initialize hook arrays\n const hookEventValues = Object.values(HOOK_EVENTS);\n const hookEventLen = hookEventValues.length;\n for (let i = 0; i < hookEventLen; i++) {\n const event = hookEventValues[i];\n if (event === undefined) continue;\n this.hooks.set(event, []);\n this.beforeHooks.set(event, []);\n this.afterHooks.set(event, []);\n // Initialize with noop functions\n this.updateExecuteCache(event);\n }\n }\n\n // Update cached execute function for an event\n private updateExecuteCache(event: string): void {\n const beforeHooks = this.beforeHooks.get(event) || [];\n const hooks = this.hooks.get(event) || [];\n const afterHooks = this.afterHooks.get(event) || [];\n\n // If no hooks registered, use noop for zero overhead\n if (beforeHooks.length === 0 && hooks.length === 0 && afterHooks.length === 0) {\n this.executeCache.set(event, async (context: HookContext) => context);\n this.hookSyncStatus.set(event, true); // Mark as sync (noop)\n this.activeEvents.delete(event);\n return;\n }\n\n this.activeEvents.add(event);\n\n // Detect if all hooks are synchronous\n const allSync = this.areHooksSynchronous(beforeHooks, hooks, afterHooks);\n this.hookSyncStatus.set(event, allSync);\n\n if (allSync) {\n // FAST PATH: Create synchronous version (no Promise overhead)\n // Cast to Promise return type to satisfy interface\n this.executeCache.set(event, ((context: HookContext) => {\n // Execute before hooks synchronously\n const beforeLen = beforeHooks.length;\n for (let i = 0; i < beforeLen; i++) {\n try {\n const hook = beforeHooks[i];\n if (hook !== undefined) {\n hook(context);\n }\n } catch (error) {\n // Check if this is a known/expected error that should not halt execution\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isHeadersError =\n errorMessage.includes('headersSent') && errorMessage.includes('getter');\n\n if (isHeadersError) {\n // This is an expected error when trying to set read-only headersSent property\n // Log as debug instead of error, and don't re-throw\n this.logger.debug(\n 'Hook attempted to set read-only headersSent property',\n 'HookExecution',\n {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n }\n );\n continue;\n }\n\n this.logger.error('Hook execution error', 'HookExecution', {\n error: errorMessage,\n });\n throw error;\n }\n }\n\n // Execute main hooks synchronously\n const hooksLen = hooks.length;\n for (let i = 0; i < hooksLen; i++) {\n try {\n const hook = hooks[i];\n if (hook !== undefined) {\n hook(context);\n }\n } catch (error) {\n // Check if this is a known/expected error that should not halt execution\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isHeadersError =\n errorMessage.includes('headersSent') && errorMessage.includes('getter');\n\n if (isHeadersError) {\n // This is an expected error when trying to set read-only headersSent property\n // Log as debug instead of error, and don't re-throw\n this.logger.debug(\n 'Hook attempted to set read-only headersSent property',\n 'HookExecution',\n {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n }\n );\n continue;\n }\n\n this.logger.error('Hook execution error', 'HookExecution', {\n error: errorMessage,\n });\n throw error;\n }\n }\n\n // Execute after hooks synchronously\n const afterLen = afterHooks.length;\n for (let i = 0; i < afterLen; i++) {\n try {\n const hook = afterHooks[i];\n if (hook !== undefined) {\n hook(context);\n }\n } catch (error) {\n // Check if this is a known/expected error that should not halt execution\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isHeadersError =\n errorMessage.includes('headersSent') && errorMessage.includes('getter');\n\n if (isHeadersError) {\n // This is an expected error when trying to set read-only headersSent property\n // Log as debug instead of error, and don't re-throw\n this.logger.debug(\n 'Hook attempted to set read-only headersSent property',\n 'HookExecution',\n {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n }\n );\n continue;\n }\n\n this.logger.error('Hook execution error', 'HookExecution', {\n error: errorMessage,\n });\n throw error;\n }\n }\n\n // Emit event for listeners\n this.emit(event, context);\n\n return context as any; // Cast to satisfy Promise return\n }) as any);\n } else {\n // SLOW PATH: Use async version only when needed\n this.executeCache.set(event, async (context: HookContext) => {\n // Execute before hooks\n const beforeLen = beforeHooks.length;\n for (let i = 0; i < beforeLen; i++) {\n const hook = beforeHooks[i];\n if (hook !== undefined) {\n await this.executeHook(hook, context);\n }\n }\n\n // Execute main hooks\n const hooksLen = hooks.length;\n for (let i = 0; i < hooksLen; i++) {\n const hook = hooks[i];\n if (hook !== undefined) {\n await this.executeHook(hook, context);\n }\n }\n\n // Execute after hooks\n const afterLen = afterHooks.length;\n for (let i = 0; i < afterLen; i++) {\n const hook = afterHooks[i];\n if (hook !== undefined) {\n await this.executeHook(hook, context);\n }\n }\n\n // Emit event for listeners\n this.emit(event, context);\n\n return context;\n });\n }\n }\n\n // Detect if hooks are synchronous by checking function signatures\n private areHooksSynchronous(...hookArrays: HookFunction[][]): boolean {\n for (const hooks of hookArrays) {\n for (const hook of hooks) {\n // Check if function is async or returns a Promise\n if (hook.constructor.name === 'AsyncFunction') {\n return false;\n }\n // Additional heuristic: check if function name suggests async\n if (hook.name && (hook.name.includes('async') || hook.name.includes('Async'))) {\n return false;\n }\n }\n }\n return true; // Assume synchronous by default\n }\n\n // Register a hook for a specific event\n hook(event: string, fn: HookFunction): this {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.hooks.get(event)!.push(fn);\n this.updateExecuteCache(event); // Update cache\n return this;\n }\n\n // Register a before hook\n before(event: string, fn: HookFunction): this {\n if (!this.beforeHooks.has(event)) {\n this.beforeHooks.set(event, []);\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.beforeHooks.get(event)!.push(fn);\n this.updateExecuteCache(event); // Update cache\n return this;\n }\n\n // Register an after hook\n after(event: string, fn: HookFunction): this {\n if (!this.afterHooks.has(event)) {\n this.afterHooks.set(event, []);\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.afterHooks.get(event)!.push(fn);\n this.updateExecuteCache(event); // Update cache\n return this;\n }\n\n // O(1) check that lets hot paths skip execute() (and its context/promise\n // allocation) entirely when no hooks are registered for an event.\n // Note: EventEmitter listeners attached via .on(event) also count, since the\n // cached executors emit the event after running hooks.\n hasHooks(event: string): boolean {\n return this.activeEvents.has(event) || this.listenerCount(event) > 0;\n }\n\n // Execute hooks for an event - optimized with cached functions\n async execute(event: string, context: HookContext = {}): Promise<HookContext> {\n const executeFn = this.executeCache.get(event);\n if (executeFn) {\n return executeFn(context);\n }\n\n // Fallback for events not in cache (shouldn't happen in normal operation)\n this.updateExecuteCache(event);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.executeCache.get(event)!(context);\n }\n\n // Execute a single hook with error handling\n private async executeHook(hook: HookFunction, context: HookContext): Promise<void> {\n try {\n await hook(context);\n } catch (error) {\n // Check if this is a known/expected error that should not halt execution\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isHeadersError =\n errorMessage.includes('headersSent') && errorMessage.includes('getter');\n\n if (isHeadersError) {\n // This is an expected error when trying to set read-only headersSent property\n // Log as debug instead of error, and don't re-throw\n this.logger.debug('Hook attempted to set read-only headersSent property', 'HookExecution', {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n });\n return;\n }\n\n // For other errors, log and re-throw as before\n this.logger.error('Hook execution error', 'HookExecution', {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n });\n throw error;\n }\n }\n\n // Remove hooks\n removeHook(event: string, fn?: HookFunction): this {\n if (!fn) {\n this.hooks.delete(event);\n this.beforeHooks.delete(event);\n this.afterHooks.delete(event);\n } else {\n const maps = [this.hooks, this.beforeHooks, this.afterHooks];\n const mapsLen = maps.length;\n for (let i = 0; i < mapsLen; i++) {\n const map = maps[i];\n if (map === undefined) continue;\n const hooks = map.get(event);\n if (hooks) {\n const index = hooks.indexOf(fn);\n if (index !== -1) {\n hooks.splice(index, 1);\n }\n }\n }\n }\n this.updateExecuteCache(event); // Update cache\n return this;\n }\n\n // Get all registered hooks for debugging\n getHooks(event?: string): Record<string, any> {\n if (event) {\n return {\n before: this.beforeHooks.get(event) || [],\n main: this.hooks.get(event) || [],\n after: this.afterHooks.get(event) || [],\n };\n }\n\n const allHooks: Record<string, any> = {};\n const allEvents = new Set([\n ...this.hooks.keys(),\n ...this.beforeHooks.keys(),\n ...this.afterHooks.keys(),\n ]);\n\n allEvents.forEach(event => {\n allHooks[event] = this.getHooks(event);\n });\n\n return allHooks;\n }\n}\n"]}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/core/utilities/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["// Hook System for Moro\nimport { EventEmitter } from 'events';\nimport { HookFunction, HookContext } from '../../types/hooks.js';\nimport { createFrameworkLogger } from '../logger/index.js';\n\n// The lifecycle events the servers actually execute. These are the exact\n// strings passed to before()/after() — the before/after phase is expressed by\n// which method you call, not by the event name. (Earlier versions exported\n// 'before:request'-style values here that were never valid registration keys.)\nexport const HOOK_EVENTS = {\n /** Pre-routing, after body parse: hooks.before/after('request', ...) */\n REQUEST: 'request',\n /** After the response is flushed: hooks.before/after('response', ...) */\n RESPONSE: 'response',\n /** When a request fails at the server error boundary: hooks.before/after('error', ...) */\n ERROR: 'error',\n} as const;\n\nexport class HookManager extends EventEmitter {\n private hooks = new Map<string, HookFunction[]>();\n private beforeHooks = new Map<string, HookFunction[]>();\n private afterHooks = new Map<string, HookFunction[]>();\n private logger = createFrameworkLogger('Hooks');\n\n // Cached execute functions\n // When no hooks are registered, replace execute() with noop\n private executeCache = new Map<string, (context: HookContext) => Promise<HookContext>>();\n\n // Track if hooks are synchronous to avoid Promise overhead\n private hookSyncStatus = new Map<string, boolean>();\n\n // Events that currently have at least one hook registered - lets callers skip\n // execute() entirely (no context object, no promise) when nothing is registered\n private activeEvents = new Set<string>();\n\n constructor() {\n super();\n // Initialize hook arrays\n const hookEventValues = Object.values(HOOK_EVENTS);\n const hookEventLen = hookEventValues.length;\n for (let i = 0; i < hookEventLen; i++) {\n const event = hookEventValues[i];\n if (event === undefined) continue;\n this.hooks.set(event, []);\n this.beforeHooks.set(event, []);\n this.afterHooks.set(event, []);\n // Initialize with noop functions\n this.updateExecuteCache(event);\n }\n }\n\n // Update cached execute function for an event\n private updateExecuteCache(event: string): void {\n const beforeHooks = this.beforeHooks.get(event) || [];\n const hooks = this.hooks.get(event) || [];\n const afterHooks = this.afterHooks.get(event) || [];\n\n // If no hooks registered, use noop for zero overhead\n if (beforeHooks.length === 0 && hooks.length === 0 && afterHooks.length === 0) {\n this.executeCache.set(event, async (context: HookContext) => context);\n this.hookSyncStatus.set(event, true); // Mark as sync (noop)\n this.activeEvents.delete(event);\n return;\n }\n\n this.activeEvents.add(event);\n\n // Detect if all hooks are synchronous\n const allSync = this.areHooksSynchronous(beforeHooks, hooks, afterHooks);\n this.hookSyncStatus.set(event, allSync);\n\n if (allSync) {\n // FAST PATH: Create synchronous version (no Promise overhead)\n // Cast to Promise return type to satisfy interface\n this.executeCache.set(event, ((context: HookContext) => {\n // Execute before hooks synchronously\n const beforeLen = beforeHooks.length;\n for (let i = 0; i < beforeLen; i++) {\n try {\n const hook = beforeHooks[i];\n if (hook !== undefined) {\n hook(context);\n }\n } catch (error) {\n // Check if this is a known/expected error that should not halt execution\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isHeadersError =\n errorMessage.includes('headersSent') && errorMessage.includes('getter');\n\n if (isHeadersError) {\n // This is an expected error when trying to set read-only headersSent property\n // Log as debug instead of error, and don't re-throw\n this.logger.debug(\n 'Hook attempted to set read-only headersSent property',\n 'HookExecution',\n {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n }\n );\n continue;\n }\n\n this.logger.error('Hook execution error', 'HookExecution', {\n error: errorMessage,\n });\n throw error;\n }\n }\n\n // Execute main hooks synchronously\n const hooksLen = hooks.length;\n for (let i = 0; i < hooksLen; i++) {\n try {\n const hook = hooks[i];\n if (hook !== undefined) {\n hook(context);\n }\n } catch (error) {\n // Check if this is a known/expected error that should not halt execution\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isHeadersError =\n errorMessage.includes('headersSent') && errorMessage.includes('getter');\n\n if (isHeadersError) {\n // This is an expected error when trying to set read-only headersSent property\n // Log as debug instead of error, and don't re-throw\n this.logger.debug(\n 'Hook attempted to set read-only headersSent property',\n 'HookExecution',\n {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n }\n );\n continue;\n }\n\n this.logger.error('Hook execution error', 'HookExecution', {\n error: errorMessage,\n });\n throw error;\n }\n }\n\n // Execute after hooks synchronously\n const afterLen = afterHooks.length;\n for (let i = 0; i < afterLen; i++) {\n try {\n const hook = afterHooks[i];\n if (hook !== undefined) {\n hook(context);\n }\n } catch (error) {\n // Check if this is a known/expected error that should not halt execution\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isHeadersError =\n errorMessage.includes('headersSent') && errorMessage.includes('getter');\n\n if (isHeadersError) {\n // This is an expected error when trying to set read-only headersSent property\n // Log as debug instead of error, and don't re-throw\n this.logger.debug(\n 'Hook attempted to set read-only headersSent property',\n 'HookExecution',\n {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n }\n );\n continue;\n }\n\n this.logger.error('Hook execution error', 'HookExecution', {\n error: errorMessage,\n });\n throw error;\n }\n }\n\n // Emit event for listeners\n this.emit(event, context);\n\n return context as any; // Cast to satisfy Promise return\n }) as any);\n } else {\n // SLOW PATH: Use async version only when needed\n this.executeCache.set(event, async (context: HookContext) => {\n // Execute before hooks\n const beforeLen = beforeHooks.length;\n for (let i = 0; i < beforeLen; i++) {\n const hook = beforeHooks[i];\n if (hook !== undefined) {\n await this.executeHook(hook, context);\n }\n }\n\n // Execute main hooks\n const hooksLen = hooks.length;\n for (let i = 0; i < hooksLen; i++) {\n const hook = hooks[i];\n if (hook !== undefined) {\n await this.executeHook(hook, context);\n }\n }\n\n // Execute after hooks\n const afterLen = afterHooks.length;\n for (let i = 0; i < afterLen; i++) {\n const hook = afterHooks[i];\n if (hook !== undefined) {\n await this.executeHook(hook, context);\n }\n }\n\n // Emit event for listeners\n this.emit(event, context);\n\n return context;\n });\n }\n }\n\n // Detect if hooks are synchronous by checking function signatures\n private areHooksSynchronous(...hookArrays: HookFunction[][]): boolean {\n for (const hooks of hookArrays) {\n for (const hook of hooks) {\n // Check if function is async or returns a Promise\n if (hook.constructor.name === 'AsyncFunction') {\n return false;\n }\n // Additional heuristic: check if function name suggests async\n if (hook.name && (hook.name.includes('async') || hook.name.includes('Async'))) {\n return false;\n }\n }\n }\n return true; // Assume synchronous by default\n }\n\n // Register a hook for a specific event\n hook(event: string, fn: HookFunction): this {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.hooks.get(event)!.push(fn);\n this.updateExecuteCache(event); // Update cache\n return this;\n }\n\n // Register a before hook\n before(event: string, fn: HookFunction): this {\n if (!this.beforeHooks.has(event)) {\n this.beforeHooks.set(event, []);\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.beforeHooks.get(event)!.push(fn);\n this.updateExecuteCache(event); // Update cache\n return this;\n }\n\n // Register an after hook\n after(event: string, fn: HookFunction): this {\n if (!this.afterHooks.has(event)) {\n this.afterHooks.set(event, []);\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.afterHooks.get(event)!.push(fn);\n this.updateExecuteCache(event); // Update cache\n return this;\n }\n\n // O(1) check that lets hot paths skip execute() (and its context/promise\n // allocation) entirely when no hooks are registered for an event.\n // Note: EventEmitter listeners attached via .on(event) also count, since the\n // cached executors emit the event after running hooks.\n hasHooks(event: string): boolean {\n return this.activeEvents.has(event) || this.listenerCount(event) > 0;\n }\n\n // Execute hooks for an event - optimized with cached functions\n async execute(event: string, context: HookContext = {}): Promise<HookContext> {\n const executeFn = this.executeCache.get(event);\n if (executeFn) {\n return executeFn(context);\n }\n\n // Fallback for events not in cache (shouldn't happen in normal operation)\n this.updateExecuteCache(event);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.executeCache.get(event)!(context);\n }\n\n // Execute a single hook with error handling\n private async executeHook(hook: HookFunction, context: HookContext): Promise<void> {\n try {\n await hook(context);\n } catch (error) {\n // Check if this is a known/expected error that should not halt execution\n const errorMessage = error instanceof Error ? error.message : String(error);\n const isHeadersError =\n errorMessage.includes('headersSent') && errorMessage.includes('getter');\n\n if (isHeadersError) {\n // This is an expected error when trying to set read-only headersSent property\n // Log as debug instead of error, and don't re-throw\n this.logger.debug('Hook attempted to set read-only headersSent property', 'HookExecution', {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n });\n return;\n }\n\n // For other errors, log and re-throw as before\n this.logger.error('Hook execution error', 'HookExecution', {\n error: errorMessage,\n context: context.request?.method || 'unknown',\n });\n throw error;\n }\n }\n\n // Remove hooks\n removeHook(event: string, fn?: HookFunction): this {\n if (!fn) {\n this.hooks.delete(event);\n this.beforeHooks.delete(event);\n this.afterHooks.delete(event);\n } else {\n const maps = [this.hooks, this.beforeHooks, this.afterHooks];\n const mapsLen = maps.length;\n for (let i = 0; i < mapsLen; i++) {\n const map = maps[i];\n if (map === undefined) continue;\n const hooks = map.get(event);\n if (hooks) {\n const index = hooks.indexOf(fn);\n if (index !== -1) {\n hooks.splice(index, 1);\n }\n }\n }\n }\n this.updateExecuteCache(event); // Update cache\n return this;\n }\n\n // Get all registered hooks for debugging\n getHooks(event?: string): Record<string, any> {\n if (event) {\n return {\n before: this.beforeHooks.get(event) || [],\n main: this.hooks.get(event) || [],\n after: this.afterHooks.get(event) || [],\n };\n }\n\n const allHooks: Record<string, any> = {};\n const allEvents = new Set([\n ...this.hooks.keys(),\n ...this.beforeHooks.keys(),\n ...this.afterHooks.keys(),\n ]);\n\n allEvents.forEach(event => {\n allHooks[event] = this.getHooks(event);\n });\n\n return allHooks;\n }\n}\n"]}
package/dist/moro.d.ts CHANGED
@@ -213,6 +213,7 @@ export declare class Moro extends EventEmitter {
213
213
  private findMatchingRoute;
214
214
  private pathToRegex;
215
215
  get events(): MoroEventBus;
216
+ get hooks(): import("./index.js").HookManager;
216
217
  get core(): MoroCore;
217
218
  get engine(): ReturnType<MoroCore['getServerKind']>;
218
219
  getServerKind(): ReturnType<MoroCore['getServerKind']>;
package/dist/moro.js CHANGED
@@ -230,6 +230,9 @@ export class Moro extends EventEmitter {
230
230
  const httpServer = this.coreFramework.httpServer;
231
231
  if (httpServer && httpServer.setHookManager) {
232
232
  httpServer.setHookManager(this.middlewareManager.hooks);
233
+ // The router swallows handler errors (it produces the 500), so it needs
234
+ // the hook manager too for 'error' hooks to observe them.
235
+ this.unifiedRouter.setHookManager(this.middlewareManager.hooks);
233
236
  }
234
237
  // Configure HTTP server performance based on config
235
238
  if (httpServer && httpServer.configurePerformance) {
@@ -1011,25 +1014,58 @@ export class Moro extends EventEmitter {
1011
1014
  error: error instanceof Error ? error.message : String(error),
1012
1015
  });
1013
1016
  });
1014
- // Create a unified request handler that works with the runtime adapter
1017
+ // Create a unified request handler that works with the runtime adapter.
1018
+ // Lifecycle hooks run here so serverless runtimes (Lambda, Edge, Workers)
1019
+ // have parity with the long-running servers. Unlike those servers,
1020
+ // 'response' hooks are awaited before returning — post-return work would
1021
+ // be frozen or dropped by the platform.
1022
+ const hookManager = this.middlewareManager.getHookManager();
1015
1023
  const handler = async (req, res) => {
1016
- // Add documentation middleware first (if enabled)
1017
1024
  try {
1018
- const docsMiddleware = this.documentation.getDocsMiddleware();
1019
- await docsMiddleware(req, res, () => { });
1020
- if (res.headersSent)
1025
+ if (hookManager.hasHooks('request')) {
1026
+ await hookManager.execute('request', { request: req, response: res });
1027
+ if (res.headersSent)
1028
+ return;
1029
+ }
1030
+ // Add documentation middleware first (if enabled)
1031
+ try {
1032
+ const docsMiddleware = this.documentation.getDocsMiddleware();
1033
+ await docsMiddleware(req, res, () => { });
1034
+ if (res.headersSent)
1035
+ return;
1036
+ }
1037
+ catch {
1038
+ // Documentation not enabled, that's fine
1039
+ }
1040
+ // Try unified router first (handles all routes)
1041
+ const handled = await this.unifiedRouter.handleRequest(req, res);
1042
+ if (handled)
1021
1043
  return;
1044
+ // Handle legacy direct routes (backward compatibility)
1045
+ if (this.routes.length > 0) {
1046
+ await this.handleDirectRoutes(req, res);
1047
+ }
1022
1048
  }
1023
- catch {
1024
- // Documentation not enabled, that's fine
1049
+ catch (error) {
1050
+ if (hookManager.hasHooks('error')) {
1051
+ try {
1052
+ await hookManager.execute('error', { request: req, response: res, error });
1053
+ }
1054
+ catch (hookError) {
1055
+ this.logger.error(`Error hook error: ${hookError?.message || hookError}`, 'Hooks');
1056
+ }
1057
+ }
1058
+ throw error;
1025
1059
  }
1026
- // Try unified router first (handles all routes)
1027
- const handled = await this.unifiedRouter.handleRequest(req, res);
1028
- if (handled)
1029
- return;
1030
- // Handle legacy direct routes (backward compatibility)
1031
- if (this.routes.length > 0) {
1032
- await this.handleDirectRoutes(req, res);
1060
+ finally {
1061
+ if (hookManager.hasHooks('response')) {
1062
+ try {
1063
+ await hookManager.execute('response', { request: req, response: res });
1064
+ }
1065
+ catch (hookError) {
1066
+ this.logger.error(`Response hook error: ${hookError?.message || hookError}`, 'Hooks');
1067
+ }
1068
+ }
1033
1069
  }
1034
1070
  };
1035
1071
  // Use the runtime adapter to create the appropriate handler
@@ -1162,6 +1198,13 @@ export class Moro extends EventEmitter {
1162
1198
  get events() {
1163
1199
  return this.eventBus;
1164
1200
  }
1201
+ // The application's live hook manager — the same instance
1202
+ // MiddlewareInterface.install() receives. Register request-lifecycle hooks
1203
+ // directly: app.hooks.before('request', ctx => {...}),
1204
+ // app.hooks.after('response', ctx => {...}).
1205
+ get hooks() {
1206
+ return this.middlewareManager.getHookManager();
1207
+ }
1165
1208
  // Access to core framework for advanced usage
1166
1209
  get core() {
1167
1210
  return this.coreFramework;