UNPKG

@boostercloud/cli

Version:

CLI of the Booster Framework, the next level of abstraction for cloud-native applications

102 lines (101 loc) 4.74 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Script = void 0; const ReaderTaskEither_1 = require("fp-ts/lib/ReaderTaskEither"); const pipeable_1 = require("fp-ts/lib/pipeable"); const Either_1 = require("fp-ts/lib/Either"); const TaskEither_1 = require("fp-ts/lib/TaskEither"); const function_1 = require("fp-ts/lib/function"); const logger_1 = require("../services/logger"); const brand_1 = require("./brand"); /** * A Script represents some steps in a booster command, it stores the initial context * implicitly, and makes it available for all of the steps that define this process. */ class Script { constructor(contextResolver, errorHandlers, action) { this.contextResolver = contextResolver; this.errorHandlers = errorHandlers; this.action = action; /** * Method that eases the creation of steps. It accepts a message to be shown in the spinner and a * function that receives the context and the input from the previous step. * From this function you must return a Promise that resolves with the value that you want to pass to the next step (if any) * * @param message Message to initialize the spinner * @param action Function that receives the config object and performs an action */ this.step = (message, action) => new Script(this.contextResolver, this.errorHandlers, (0, pipeable_1.pipe)(this.action, (0, ReaderTaskEither_1.chain)(() => (0, ReaderTaskEither_1.ask)()), (0, ReaderTaskEither_1.chain)((ctx) => (0, ReaderTaskEither_1.fromTaskEither)((0, TaskEither_1.tryCatch)(async () => { Script.logger.start(message); await action(ctx); Script.logger.succeed(message); }, (err) => { Script.logger.fail(message); return err; }))))); /** * Function to determine next action depending on passed boolean condition * If condition is true, step will be skipped and info action will be called. * Otherwise, step method will be called as usual. * * @param skipCondition When true, the action is skipped * @param message Message to initialize the spinner * @param action Function that receives the config object and performs an action */ this.optionalStep = (skipCondition, message, action) => { if (skipCondition) return this.info(brand_1.default.mellancholize(`Skipping: ${message}`)); return this.step(message, action); }; /** * Convenience method to generate a step that just prints a message with a small blue `i` character in front of it. * * @param message Message to be shown in the CLI */ this.info = (message) => new Script(this.contextResolver, this.errorHandlers, (0, pipeable_1.pipe)(this.action, (0, ReaderTaskEither_1.chain)(() => (0, ReaderTaskEither_1.rightIO)(() => { Script.logger.info(message); })))); /** * Add a handler to catch a specific type of errors * * @param errorType the kind of errors that the handler will catch * @param handler handler for the errors */ this.catch = (errorType, handler) => { const newHandlers = { ...this.errorHandlers }; newHandlers[errorType] = handler; return new Script(this.contextResolver, newHandlers, this.action); }; } /** * Function to finish the script, * it will handle any error in between that might happen in * some steps. */ async done() { try { const context = await this.contextResolver; const result = await (0, ReaderTaskEither_1.run)(this.action, context); return (0, pipeable_1.pipe)(result, (0, Either_1.fold)((err) => { throw err; }, function_1.constVoid)); } catch (err) { const error = err; const defaultHandler = (e) => e.stack || e.message || JSON.stringify(e); const handler = this.errorHandlers[error.name] || defaultHandler; throw new Error(handler(error)); } } } exports.Script = Script; /** * Convenience function to print a welcome message and initialize the context of the script * * @param initialMessage The message to show in the console * @param contextResolver A promise that fulfills into a valid context object */ Script.init = (initialMessage, contextResolver) => new Script(contextResolver, {}, (0, ReaderTaskEither_1.rightIO)(() => { Script.logger.info(initialMessage); })); Script.logger = logger_1.oraLogger;