UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

171 lines 6.44 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("@sprucelabs/error")); const schema_1 = __importDefault(require("@sprucelabs/schema")); const lodash_1 = require("lodash"); const SpruceError_1 = __importDefault(require("../errors/SpruceError")); const graphicsInterface_types_1 = require("../types/graphicsInterface.types"); var FormBuilderActionType; (function (FormBuilderActionType) { FormBuilderActionType["Done"] = "done"; FormBuilderActionType["Cancel"] = "cancel"; FormBuilderActionType["EditField"] = "edit_field"; })(FormBuilderActionType || (FormBuilderActionType = {})); class FormComponent extends schema_1.default { ui; handlers = {}; constructor(options) { // Setup schema super(options.schema, options.initialValues); const { ui } = options; // Save ui for writing, saving this.ui = ui; // Handlers const { onWillAskQuestion } = options; this.handlers.onWillAskQuestion = onWillAskQuestion; } /** Pass me a schema and i'll give you back an object that conforms to it based on user input */ async present(options = {}) { const { ui } = this; const { headline, showOverview, fields = this.getNamedFields().map((nf) => nf.name), } = options; let done = false; let valid = false; do { if (headline) { ui.renderHeadline(headline, [graphicsInterface_types_1.GraphicsTextEffect.SpruceHeader]); ui.renderLine(''); } if (showOverview) { // Overview mode const action = await this.renderOverview({ fields }); switch (action.type) { case FormBuilderActionType.EditField: { // Editing a field const fieldName = action.fieldName; const answer = await this.askQuestion(fieldName); // Set the new value this.set(fieldName, answer); break; } case FormBuilderActionType.Done: { done = true; } } } else { // Asking one question at a time const namedFields = this.getNamedFields({ fields }); for (const namedField of namedFields) { const { name } = namedField; const answer = await this.askQuestion(name); this.set(name, answer); } done = true; } if (done) { try { this.validate({ fields }); valid = true; } catch (err) { this.renderError(err); await this.ui.waitForEnter(); } } } while (!done || !valid); const values = this.getValues({ fields, shouldCreateEntityInstances: false, }); const cleanValues = (0, lodash_1.pick)(values, fields); return cleanValues; } /** Ask a question based on a field */ askQuestion(fieldName) { const field = this.getNamedFields().find((nf) => nf.name === fieldName)?.field; if (!field) { throw new Error(`No field named ${fieldName} on form ${this.schemaId}`); } let definition = { ...field.definition }; const value = this.get(fieldName, { shouldValidate: false, shouldCreateEntityInstances: false, }); if (definition.isArray) { throw new SpruceError_1.default({ code: 'NOT_IMPLEMENTED', friendlyMessage: 'Form builder does not support isArray yet', }); } if (value) { definition.defaultValue = value; } if (this.handlers.onWillAskQuestion) { definition = this.handlers.onWillAskQuestion(fieldName, //@ts-ignore definition, this.getValues({ shouldValidate: false, shouldCreateEntityInstances: false, })); } return this.ui.prompt(definition); } renderError(error) { this.ui.renderDivider(); this.ui.renderHeadline('Please fix the following...', [ graphicsInterface_types_1.GraphicsTextEffect.Red, graphicsInterface_types_1.GraphicsTextEffect.Bold, ]); this.ui.renderLine(''); if (error instanceof error_1.default) { this.ui.renderWarning(error.friendlyMessage()); } else { this.ui.renderWarning(`Unexpected error ${error.message}`); } this.ui.renderLine(''); } async renderOverview(options = {}) { const { ui } = this; const { fields = this.getNamedFields().map((nf) => nf.name) } = options; const actionMap = {}; const choices = this.getNamedFields() .filter((namedField) => fields.indexOf(namedField.name) > -1) .map((namedField) => { const { field, name } = namedField; const actionKey = `field:${name}`; const action = { type: FormBuilderActionType.EditField, fieldName: name, }; actionMap[actionKey] = action; const value = this.get(name, { shouldValidate: false }); return { value: actionKey, label: `${field.label}: ${value ? value : '***missing***'}`, }; }); actionMap['done'] = { type: FormBuilderActionType.Done, }; choices.push({ value: 'done', label: 'Done', }); const response = await ui.prompt({ type: 'select', isRequired: true, label: 'Select any field to edit', options: { choices, }, }); const action = actionMap[response]; return action; } } exports.default = FormComponent; //# sourceMappingURL=FormComponent.js.map