Gauntlet Core
TODO: Explain the package and its components: Operations, Client, Dependencies, Operation Runner, etc.
Interceptors
Interceptors are used to extract and treat information that goes through the Gauntlet Client.
The Gauntlet Client expects an optional interceptors
parameter, which is an optional list of implementations of the ClientInterceptor
interface. As ClientInterceptor
intercepts Gauntlet Client calls, is expected that the interface has similarities with the Gauntlet Client interface.
export interface ClientInterceptor {
execute: (input: InterceptorExecuteInput, next: Next<this, 'execute'>) => Promise<Report>
plan: (input: InterceptorPlanInput, next: Next<this, 'plan'>) => Promise<Report>
query: (input: InterceptorQueryInput, next: Next<this, 'query'>) => Promise<Report>
}
A simple implementation could just be for logging purposes:
export class LoggerClientInterceptor implements ClientInterceptor {
readonly log: Logger
constructor(logger: Logger) {
this.log = logger
}
async execute(
input: InterceptorExecuteInput,
next: Next<ClientInterceptor, 'execute'>,
): Promise<ReportAny> {
this.log.info(`Execution starting with plan: ${JSON.stringify(input.plan)}`)
const report = await next(input)
this.log.info(`Execution finished with report: ${JSON.stringify(report)}`)
return report
}
async plan(
input: InterceptorPlanInput,
next: Next<ClientInterceptor, 'plan'>,
): Promise<ReportAny> {
this.log.info(`Command plan stage starting with input: ${JSON.stringify(input.input)}`)
const report = await next(input)
this.log.info(`Plan stage finished with report: ${JSON.stringify(report)}`)
return report
}
}
The user can enable many Interceptors in the client by just providing implementations of ClientInterceptor
;(async () => {
const client = buildClient(packages, factories, [
new LoggerClientInterceptor(),
new TracingInterceptor(),
])
const report = client.plan(op.def, input, config, traceExtra)
})()
Operations
TODO!
RuntimeContext
TODO!
Ctx.Emit
The ctx.emit
function allows developers to add custom events with associated data when planning an operation, which can then be aggregated or reported in a structured format.
Using ctx.emit
The ctx.emit
function is defined as follows:
emit: (msg: string, payload?: EventPayload) => void
Parameters
- msg: A string message describing the event.
- payload: An optional parameter that includes the type and properties defining the event.
Examples
-
Emitting a Diff Event
When there's a change in state that needs to be captured:
ctx.emit('Would add a new owner to the safe', asDiffEvent(prev, head))
-
Emitting a Generic Event
For less structured events:
ctx.emit('Any event', { type: 'any', object: 5, a: { c: 2 } })
-
Emitting Without Payload
Simply sending a message without additional data:
ctx.emit('without payload')