lib-intercept
Library for executing reflected ClassData and allowing intercepting of a method execution and result. The interceptors can be optimized away on methods that do not need them depending on how the interceptors are implemented.
- At startup (activation generation) - IConfiguration will be executed at Activation generation on interceptors that implement it
- At runtime - On Before / After handlers can remove the interceptor by using methods on the activation object.
It is using the lib-reflect library in order to generate the needed information for executing a method on a class.
Installation
Standard npm package install
npm i lib-intercept
Overview
The execution will happen in an execution context. The execution of the method(s) does not throw even if an error happens. The error will be available on the context result object.
The library add's two interceptors by default
- An interceptor that scan's the method parameters for types it can find in the
inversify
container- The method invocation is implemented as an interceptor that get's the 'IActivation' object from the context and call's the target method on an instance of the target class. The class instance is created using
inversify
if it is bound, meaning you can inject services on the target class.
There are several layers of interceptors that can be added.
- At the global level in the ActivationsGenerator class. Those interceptors will execute for all methods on all registered classes.
- At the class level, those interceptors will execute only on the methods from that class.
- At the method level, those interceptors will execute only on the target method.
The IContext will contain information regarding the execution of the target method. Like:
- The activation information
- Arguments to be passed to the method (at first it's an array of 'null' with length equal to the number of arguments). It is the job of the interceptors to set values on the arguments.
- A dictionary to store custom data on the context to be passed around.
- The result object, it contains either the result of the executing method, or the error.
- The inversify container used for DI in case we need something in an interceptor.
Order of interceptor execution withing a group
The order of interceptor executions within an interceptor group depends on the type of interceptor
Before interceptors
The order of the before interceptors is as they are used / defined, in the example bellow the call chain will be I1 -> I2 -> I3.
// Call chain I1 -> I2 -> I3
After interceptors
The order of the after interceptors is in reverse order of the usage , in the example bellow the call chain will be A1 -> A2 -> A3.
// Call chain A1 -> A2 -> A3
The reason is that we can't add decorators after a method. Ideally we would have
public myMethod
So we are left with figuring out a way to set interceptors and still know how they are executed, so the way this library does it, is basically moving the interceptors from the example above, on top of the method.
//public myMethod(){} public myMethod // I1 -> I2 -> myMethod() -> A2 -> A1
You can mix and match the usage of the decorators, however that will make it a lot harder to understand the ordering
Example
For a complex example go to lib-intercept-example
Simple
// Interceptors for method execution // Create a test class ;// We can register as many classes as we want, for this example we only have onegenerator.registerTestClass;// Generate the activations// We have only one class with one method however we also have a 'constructor' method// We don't need to check the class name since we only registered one;// Create the context of execution;context.execute.then;
Custom Context
An example of a custom context for integrating with express and passing the request / response objects to interceptors
// Either extend or implement a custom IContext...// In the request handler;ctx.execute.then;