This directory contains providers contributing additional bindings, for example custom sequence actions.
A provider
is a class that provides a value() function. This function is called Context
when another entity requests a value to be injected.
Here we create a provider for a logging function that can be used as a new action in a custom sequence.
The logger will log the URL, the parsed request parameters, and the result. The
logger is also capable of timing the sequence if you start a timer at the start
of the sequence using this.logger.startTimer().
TimerProvider is automatically bound to your Application's
Context using the LogComponent
which exports this provider with a binding key of extension-starter.timer. You
can learn more about components in the
related resources section.
This provider makes availble to your application a timer function which given a start time (given as an array [seconds, nanoseconds]) can give you a total time elapsed since the start in milliseconds. The timer can also start timing if no start time is given. This is used by LogComponent to allow a user to time a Sequence.
NOTE: You can get the start time in the required format by using
this.logger.startTimer().
You can provide your own implementation of the elapsed time function by binding
it to the binding key (accessible via ExtensionStarterBindings) as follows:
app.bind(ExtensionStarterBindings.TIMER).to(timerFn);LogProvider can automatically be bound to your Application's Context using the
LogComponent which exports the provider with a binding key of
extension-starter.actions.log.
The key can be accessed by importing ExtensionStarterBindings as follows:
Example: Binding Keys
import {ExtensionStarterBindings} from 'HelloExtensions';
// Key can be accessed as follows now
const key = ExtensionStarterBindings.LOG_ACTION;LogProvider gives us a seuqence action and a startTimer function. In order to
use the sequence action, you must define your own sequence as shown below.
Example: Sequence
class LogSequence implements SequenceHandler {
constructor(
@inject(coreSequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
@inject(coreSequenceActions.PARSE_PARAMS)
protected parseParams: ParseParams,
@inject(coreSequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
@inject(coreSequenceActions.SEND) protected send: Send,
@inject(coreSequenceActions.REJECT) protected reject: Reject,
// We get the logger injected by the LogProvider here
@inject(ExtensionStarterBindings.LOG_ACTION) protected logger: LogFn,
) {}
async handle(context: RequestContext) {
const {request, response} = context;
// We define these variable outside so they can be accessed by logger.
let args: any = [];
let result: any;
// Optionally start timing the sequence using the timer
// function available via LogFn
const start = this.logger.startTimer();
try {
const route = this.findRoute(request);
args = await this.parseParams(request, route);
result = await this.invoke(route, args);
this.send(response, result);
} catch (error) {
result = error; // so we can log the error message in the logger
this.reject(context, error);
}
// We call the logger function given to us by LogProvider
this.logger(request, args, result, start);
}
}Once a sequence has been written, we can just use that in our Application as follows:
Example: Application
const app = new Application({
sequence: LogSequence,
});
app.component(LogComponent);
// Now all requests handled by our sequence will be logged.You can check out the following resource to learn more about providers, components, sequences, and binding keys.