@atomist/automation-client
Version:
Atomist API for software low-level client
74 lines (64 loc) • 3.33 kB
text/typescript
import * as _ from "lodash";
import { EventFired } from "../HandleEvent";
import { HandlerContext } from "../HandlerContext";
import { HandlerResult } from "../HandlerResult";
import {
Arg,
CommandInvocation,
} from "../internal/invoker/Payload";
import { Automations } from "../internal/metadata/metadata";
import {
CommandHandlerMetadata,
EventHandlerMetadata,
} from "../metadata/automationMetadata";
import { AutomationServer } from "./AutomationServer";
export const NoEventHandlersError = "NO_EVENT_HANDLERS";
export function noEventHandlersWereFound(result: HandlerResult) {
return result.code !== 0 && !!result.message && result.message.startsWith(NoEventHandlersError);
}
/**
* Support for implementing an automation server.
*/
export abstract class AbstractAutomationServer implements AutomationServer {
public abstract automations: Automations;
public invokeCommand(payload: CommandInvocation, ctx: HandlerContext): Promise<HandlerResult> {
const h = this.validateCommandInvocation(payload);
return this.invokeCommandHandler(payload, h, ctx);
}
public onEvent(payload: EventFired<any>, ctx: HandlerContext): Promise<HandlerResult[]> {
const h = this.automations.events.filter(eh => eh.subscriptionName === payload.extensions.operationName);
if (!h || h.length === 0) {
throw new Error(`${NoEventHandlersError}: No event handler with name '${payload.extensions.operationName}'` +
`: Known event handlers are '${this.automations.events.map(e => e.name)}'`);
} else {
return Promise.all(h.map(eh => this.invokeEventHandler(payload, eh, ctx)));
}
}
public validateCommandInvocation(payload: CommandInvocation): CommandHandlerMetadata {
const handler = this.automations.commands.find(h => h.name === payload.name);
if (!handler) {
throw new Error(`No command handler with name '${payload.name}'` +
`: Known command handlers are '${this.automations.commands.map(c => c.name)}'`);
}
handler.parameters.forEach(p => {
const payloadValue: Arg = payload.args ?
payload.args.find(a => a.name === p.name) : undefined;
if (!payloadValue || _.isNil(payloadValue.value)) {
if (p.required && p.default_value === undefined) {
throw new Error(`Parameter '${p.name}' required but missing in invocation to '${handler.name}'`);
}
} else {
// We have a parameter. Validate it
if (p.pattern && payloadValue.value.toString().match(new RegExp(p.pattern)) === null) {
throw new Error(`Parameter '${p.name}' value of '${payloadValue.value}'` +
` invalid in invocation to '${handler.name}' with pattern '${p.pattern}'`);
}
}
});
return handler;
}
protected abstract invokeCommandHandler(payload: CommandInvocation, h: CommandHandlerMetadata,
ctx: HandlerContext): Promise<HandlerResult>;
protected abstract invokeEventHandler(payload: EventFired<any>, h: EventHandlerMetadata,
ctx: HandlerContext): Promise<HandlerResult>;
}