From 796592f8d5cb252106eeaa029ba9cc6a053b655b Mon Sep 17 00:00:00 2001 From: Corey Pyle Date: Thu, 12 Oct 2023 16:40:37 -0400 Subject: [PATCH] JavaScript (v3): Add scenario runner. --- javascriptv3/example_code/libs/scenario.js | 115 +++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 javascriptv3/example_code/libs/scenario.js diff --git a/javascriptv3/example_code/libs/scenario.js b/javascriptv3/example_code/libs/scenario.js new file mode 100644 index 00000000000..1fe98139eec --- /dev/null +++ b/javascriptv3/example_code/libs/scenario.js @@ -0,0 +1,115 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Prompter } from "./prompter.js"; +import { Logger } from "./logger.js"; +import { SlowLogger } from "./slow-logger.js"; + +class Step { + /** + * @param {string} name + */ + constructor(name) { + this.name = name; + } +} + +export class ScenarioOutput extends Step { + /** + * @param {string} name + * @param {string | (context: Record) => string} value + * @param {{ slow: boolean }} options + */ + constructor(name, value, options = { slow: true }) { + super(name); + this.value = value; + this.options = options; + this.slowLogger = new SlowLogger(20); + this.logger = new Logger(); + } + + /** + * @param {Record} context + */ + async handle(context) { + const output = + typeof this.value === "function" ? this.value(context) : this.value; + const logger = this.options.slow ? this.slowLogger : this.logger; + await logger.log(JSON.stringify(output)); + } +} + +export class ScenarioInput extends Step { + /** + * @param {string} name + * @param {string} prompt + * @param {{ type: "input" | "multi-select" | "select", choices: { name: string, value: string }[]} options + */ + constructor(name, prompt, options) { + super(name); + this.prompt = prompt; + this.options = options; + this.prompter = new Prompter(); + } + + /** + * @param {Record} context + */ + async handle(context) { + if (this.options.type === "multi-select") { + context[this.name] = await this.prompter.checkbox({ + message: this.prompt, + choices: this.options.choices, + }); + } else if (this.options.type === "select") { + context[this.name] = await this.prompter.select({ + message: this.prompt, + choices: this.options.choices, + }); + } else if (this.options.type === "input") { + context[this.name] = await this.prompter.input({ message: this.prompt }); + } else { + throw new Error( + `Error handling ScenarioInput, ${this.options.type} is not supported.`, + ); + } + } +} + +export class ScenarioAction extends Step { + /** + * + * @param {string} name + * @param {(context: Record) => Promise} action + */ + constructor(name, action) { + super(name); + this.action = action; + } + + async handle(context) { + await this.action(context); + } +} + +export class Scenario { + /** + * @type {Record} + */ + context = {}; + + /** + * @param {(ScenarioOutput | ScenarioInput | ScenarioAction)[]} steps + */ + constructor(steps = []) { + this.steps = steps; + } + + async run() { + for (const step of this.steps) { + await step.handle(this.context); + } + } +}