UNPKG

@atomist/rugs

Version:

Helper functions for Rugs

233 lines (232 loc) 9.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Handlers_1 = require("@atomist/rug/operations/Handlers"); var Decorators_1 = require("@atomist/rug/operations/Decorators"); /** * Builder Pattern implementation to generate the * HandlerChainDescriptor datastructure */ var HandlerChain = (function () { function HandlerChain(handle) { this.handle = handle; } HandlerChain.prototype.onAny = function (builder) { this.any = builder; return this; }; HandlerChain.prototype.onSuccess = function (builder) { this.success = builder; return this; }; HandlerChain.prototype.onError = function (builder) { this.error = builder; return this; }; HandlerChain.prototype.build = function () { var chain = { handle: this.handle }; if (this.any !== undefined) { chain.onAny = this.any.build(); } if (this.success !== undefined) { chain.onSuccess = this.success.build(); } if (this.error !== undefined) { chain.onError = this.error.build(); } return chain; }; return HandlerChain; }()); exports.HandlerChain = HandlerChain; /** * Wrapper around a normal Handler Instruction and any parameters to be passed * downstream any Response Handlers (if any) */ var ChainedInstruction = (function () { function ChainedInstruction(instruction, params) { this.instruction = instruction; this.params = params; } return ChainedInstruction; }()); exports.ChainedInstruction = ChainedInstruction; /** * Extend this class to have Instructions and Response Handlers automatically * generated from a HandlerChainDescriptor that describes your workflow. * * Currently only Instructions can be added to the CommandPlan, and only Response * Handlers can be used to respond to their success or failure. Message sending * is currently not supported. */ var ResponseChainingCommandHandler = (function () { /** * In general, onSuccess or onAny should be passed in to make this Handler * useful. * * @param onSuccess handler chain to run if the root Instruction is successful * @param onError handler chain to run if the root Instruction fails * @param onAny handler chain to run onSuccess and on Error */ function ResponseChainingCommandHandler(onSuccess, onError, onAny) { this.onSuccess = onSuccess; this.onError = onError; this.onAny = onAny; this.rootSuccessName = "RootSuccessHandler"; this.rootErrorName = "RootErrorHandler"; this.defaultErrorHandlerName = "DefaultErrorHandler"; this.handlers = []; } /** * Configure a default onError Response Handler to use if none already * set for that node in the workflow * @param defaultErrorHandler a ChainedResponseHandler to use onError */ ResponseChainingCommandHandler.prototype.withDefaultErrorHandler = function (defaultErrorHandler) { this.defaultErrorHandler = defaultErrorHandler; var handler = new GeneratedCommandResponseHandler(this.defaultErrorHandler, undefined, undefined); // tslint:disable-next-line:max-line-length var decorated = Decorators_1.declareResponseHandler(handler, "Generated Default Error Handler", this.defaultErrorHandlerName); // hide from the CLI/Bot Decorators_1.setScope(decorated, "archive"); this.handlers.push(decorated); return this; }; /** * Called by Rug to handle a command. It delegates to `init` * so that sub-classes can configure an initial Instruction to run * to kick of the workflow * @param ctx same context passed to all Command Handlers */ ResponseChainingCommandHandler.prototype.handle = function (ctx) { var plan = new Handlers_1.CommandPlan(); var root = this.init(ctx); var respondable = { instruction: root.instruction, }; if (this.onSuccess !== undefined || this.onAny !== undefined) { respondable.onSuccess = { kind: "respond", name: this.rootSuccessName, parameters: root.params, }; } if (this.onError !== undefined || this.onAny !== undefined) { respondable.onError = { kind: "respond", name: this.rootErrorName, parameters: root.params, }; } if (respondable.onError === undefined && this.onAny !== undefined && this.defaultErrorHandler !== undefined) { respondable.onError = { kind: "respond", name: this.defaultErrorHandlerName, parameters: root.params, }; } plan.add(respondable); return plan; }; /** * Walks the HandlerChainDescriptor and generates an array of handlers * that can be exported and picked up by the Rug. */ ResponseChainingCommandHandler.prototype.buildHandlerChain = function () { if (this.onAny !== undefined && (this.onSuccess !== undefined || this.onError !== undefined)) { throw new Error("onAny and an onSuccess/onError handler have been defined"); } // walk the three trees this.walk(this.onAny, this.rootSuccessName, this.rootErrorName); this.walk(this.onError, undefined, this.rootErrorName); this.walk(this.onSuccess, this.rootSuccessName, undefined); // make sure this handler itself is registered this.handlers.push(this); return this.handlers; }; /** * Guts of the tree walking. * Currently we do _not_ use a cache to ensure * we don't generate duplicate response handlers. */ ResponseChainingCommandHandler.prototype.walk = function (chain, onSuccess, onError) { var nextOnSuccess; var nextOnError; if (chain === undefined) { return; } if (chain.onSuccess !== undefined || chain.onAny !== undefined) { nextOnSuccess = "GeneratedSuccessResponseHandler-" + this.handlers.length; } if (chain.onError !== undefined || chain.onAny !== undefined) { nextOnError = "GeneratedErrorResponseHandler-" + this.handlers.length; } else if (this.defaultErrorHandler !== undefined) { nextOnError = this.defaultErrorHandlerName; } if (onSuccess !== undefined) { var handler = new GeneratedCommandResponseHandler(chain.handle, nextOnSuccess, nextOnError); var decorated = Decorators_1.declareResponseHandler(handler, "Generated Command Response Handler", onSuccess); Decorators_1.setScope(decorated, "archive"); this.handlers.push(decorated); } if (onError !== undefined) { var handler = new GeneratedCommandResponseHandler(chain.handle, nextOnSuccess, nextOnError); var decorated = Decorators_1.declareResponseHandler(handler, "Generated Command Response Handler", onError); Decorators_1.setScope(decorated, "archive"); this.handlers.push(decorated); } this.walk(chain.onSuccess, nextOnSuccess, undefined); this.walk(chain.onError, undefined, nextOnError); this.walk(chain.onAny, nextOnSuccess, nextOnError); }; return ResponseChainingCommandHandler; }()); exports.ResponseChainingCommandHandler = ResponseChainingCommandHandler; /** * Instances of this class are created by ResponseChainingCommandHandler * and wired up with the appropriate Instructions. * * In general, they are named in an automated way and are hidden from * the CLI/Bot */ var GeneratedCommandResponseHandler = (function () { function GeneratedCommandResponseHandler(impl, onSuccess, onError) { this.impl = impl; this.onSuccess = onSuccess; this.onError = onError; } GeneratedCommandResponseHandler.prototype.handle = function (response) { var plan = new Handlers_1.CommandPlan(); // filter out stuff from this that aren't parameters var params = {}; var that = this; // tslint:disable-next-line:forin for (var k in this) { if (that.hasOwnProperty(k)) { params[k] = that[k]; } } var chainedInstruction = this.impl.call(this, response, params); var respondable = { instruction: chainedInstruction.instruction, }; if (this.onSuccess !== undefined) { respondable.onSuccess = { kind: "respond", name: this.onSuccess, parameters: chainedInstruction.params, }; } if (this.onError !== undefined) { respondable.onError = { kind: "respond", name: this.onError, parameters: chainedInstruction.params, }; } plan.add(respondable); return plan; }; return GeneratedCommandResponseHandler; }()); exports.GeneratedCommandResponseHandler = GeneratedCommandResponseHandler;