UNPKG

type2docfx

Version:

A tool to convert json format output from TypeDoc to universal reference model for DocFx to consume.

334 lines 12.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const waterfall_1 = require("./waterfall"); /** * A related set of dialogs that can all call each other. * * **Example usage:** * * ```JavaScript * const { Bot, MemoryStorage, BotStateManager } = require('botbuilder'); * const { ConsoleAdapter } = require('botbuilder-node'); * const { DialogSet } = require('botbuilder-dialogs'); * * const dialogs = new DialogSet(); * * dialogs.add('greeting', [ * function (context) { * context.reply(`Hello... I'm a bot :)`); * return dialogs.end(context); * } * ]); * * const adapter = new ConsoleAdapter().listen(); * const bot = new Bot(adapter) * .use(new MemoryStorage()) * .use(new BotStateManager()) * .onReceive((context) => { * return dialogs.continue(context).then(() => { * // If nothing has responded start greeting dialog * if (!context.responded) { * return dialogs.begin(context, 'greeting'); * } * }); * }); * ``` */ class DialogSet { /** * Creates an empty dialog set. The ability to name the sets dialog stack means that multiple * stacks can coexist within the same bot. Middleware can use their own private set of * dialogs without fear of colliding with the bots dialog stack. * * **Example usage:** * * ```JavaScript * const dialogs = new DialogSet('myPrivateStack'); * ``` * @param stackName (Optional) name of the field to store the dialog stack in off the bots conversation state object. This defaults to 'dialogStack'. */ constructor(stackName) { this.dialogs = {}; this.stackName = stackName || 'dialogStack'; } add(dialogId, dialogOrSteps) { if (this.dialogs.hasOwnProperty(dialogId)) { throw new Error(`DialogSet.add(): A dialog with an id of '${dialogId}' already added.`); } return this.dialogs[dialogId] = Array.isArray(dialogOrSteps) ? new waterfall_1.Waterfall(dialogOrSteps) : dialogOrSteps; } /** * Pushes a new dialog onto the dialog stack. * * **Example usage:** * * ```JavaScript * return dialogs.begin(context, 'greeting', user); * ``` * @param context Context object for the current turn of conversation with the user. * @param dialogId ID of the dialog to start. * @param dialogArgs (Optional) additional argument(s) to pass to the dialog being started. */ begin(context, dialogId, dialogArgs) { try { // Lookup dialog const dialog = this.find(dialogId); if (!dialog) { throw new Error(`DialogSet.begin(): A dialog with an id of '${dialogId}' wasn't found.`); } // Push new instance onto stack. const instance = { id: dialogId, state: {} }; this.getStack(context).push(instance); // Call dialogs begin() method. return Promise.resolve(dialog.begin(context, this, dialogArgs)); } catch (err) { return Promise.reject(err); } } /** * Helper function to simplify formatting the options for calling a prompt dialog. This helper will * construct a `PromptOptions` structure and then call [begin(context, dialogId, options)](#begin). * * **Example usage:** * * ```JavaScript * return dialogs.prompt(context, 'confirmPrompt', `Are you sure you'd like to quit?`); * ``` * @param O (Optional) type of options expected by the prompt. * @param context Context object for the current turn of conversation with the user. * @param dialogId ID of the prompt to start. * @param prompt Initial prompt to send the user. * @param choicesOrOptions (Optional) array of choices to prompt the user for or additional prompt options. */ prompt(context, dialogId, prompt, choicesOrOptions, options) { const args = Object.assign({}, Array.isArray(choicesOrOptions) ? { choices: choicesOrOptions } : choicesOrOptions); if (prompt) { args.prompt = prompt; } return this.begin(context, dialogId, args); } /** * Continues execution of the active dialog, if there is one, by passing the context object to * its `Dialog.continue()` method. You can check `context.responded` after the call completes * to determine if a dialog was run and a reply was sent to the user. * * **Example usage:** * * ```JavaScript * return dialogs.continue(context).then(() => { * if (!dialog.responded) { * return dialogs.begin(context, 'fallback'); * } * }); * ``` * @param context Context object for the current turn of conversation with the user. */ continue(context) { try { if (this.getStack(context).length > 0) { // Get current dialog instance const instance = this.getInstance(context); // Lookup dialog const dialog = this.find(instance.id); if (!dialog) { throw new Error(`DialogSet.continue(): Can't continue dialog. A dialog with an id of '${instance.id}' wasn't found.`); } // Check for existence of a continue() method if (dialog.continue) { // Continue execution of dialog return Promise.resolve(dialog.continue(context, this)); } else { // Just end the dialog return this.end(context); } } else { return Promise.resolve(); } } catch (err) { return Promise.reject(err); } } /** * Ends a dialog by popping it off the stack and returns an optional result to the dialogs * parent. The parent dialog is the dialog the started the on being ended via a call to * either [begin()](#begin) or [prompt()](#prompt). * * The parent dialog will have its `Dialog.resume()` method invoked with any returned * result. If the parent dialog hasn't implemented a `resume()` method then it will be * automatically ended as well and the result passed to its parent. If there are no more * parent dialogs on the stack then processing of the turn will end. * * **Example usage:** * * ```JavaScript * dialogs.add('showUptime', [ * function (context) { * const elapsed = new Date().getTime() - started; * context.reply(`I've been running for ${elapsed / 1000} seconds.`); * return dialogs.end(context, elapsed); * } * ]) * const started = new Date().getTime(); * ``` * @param context Context object for the current turn of conversation with the user. * @param result (Optional) result to pass to the parent dialogs `Dialog.resume()` method. */ end(context, result) { try { // Pop current dialog off the stack const stack = this.getStack(context); if (stack.length > 0) { stack.pop(); } // Resume previous dialog if (stack.length > 0) { // Get dialog instance const instance = this.getInstance(context); // Lookup dialog const dialog = this.find(instance.id); if (!dialog) { throw new Error(`DialogSet.end(): Can't resume previous dialog. A dialog with an id of '${instance.id}' wasn't found.`); } // Check for existence of a resumeDialog() method if (dialog.resume) { // Return result to previous dialog return Promise.resolve(dialog.resume(context, this, result)); } else { // Just end the dialog return this.end(context); } } else { return Promise.resolve(); } } catch (err) { return Promise.reject(err); } } /** * Deletes any existing dialog stack thus cancelling all dialogs on the stack. * * **Example usage:** * * ```JavaScript * return dialogs.endAll(context) * .then(() => dialogs.begin(context, 'addAlarm')); * ``` * @param context Context object for the current turn of conversation with the user. */ endAll(context) { try { // Cancel any current dialogs const state = getConversationState(context); state[this.stackName] = []; return Promise.resolve(); } catch (err) { return Promise.reject(err); } } /** * Finds a dialog that was previously added to the set using [add()](#add). * * **Example usage:** * * ```JavaScript * const dialog = dialogs.find('greeting'); * ``` * @param T (Optional) type of dialog returned. * @param dialogId ID of the dialog/prompt to lookup. */ find(dialogId) { return this.dialogs.hasOwnProperty(dialogId) ? this.dialogs[dialogId] : undefined; } /** * Returns the dialog stack persisted for a conversation. * * **Example usage:** * * ```JavaScript * const hasActiveDialog = dialogs.getStack(context).length > 0; * ``` * @param context Context object for the current turn of conversation with the user. */ getStack(context) { const state = getConversationState(context); if (!Array.isArray(state[this.stackName])) { state[this.stackName] = []; } return state[this.stackName]; } /** * Returns the active dialog instance on the top of the stack. Throws an error if the stack is * empty so use `dialogs.getStack(context).length > 0` to protect calls where the stack could * be empty. * * **Example usage:** * * ```JavaScript * const dialogState = dialogs.getInstance(context).state; * ``` * @param T (Optional) type of dialog state being persisted by the instance. * @param context Context object for the current turn of conversation with the user. */ getInstance(context) { const stack = this.getStack(context); if (stack.length < 1) { throw new Error(`DialogSet.getInstance(): No active dialog on the stack.`); } return stack[stack.length - 1]; } /** * Ends the current dialog and starts a new dialog in its place. This is particularly useful * for creating loops or redirecting to another dialog. * * **Example usage:** * * ```JavaScript * dialogs.add('loop', [ * function (context, args) { * dialogs.getInstance(context).state = args; * return dialogs.begin(context, args.dialogId); * }, * function (context) { * const args = dialogs.getInstance(context).state; * return dialogs.replace(context, 'loop', args); * } * ]); * ``` * @param context Context object for the current turn of conversation with the user. * @param dialogId ID of the new dialog to start. * @param dialogArgs (Optional) additional argument(s) to pass to the new dialog. */ replace(context, dialogId, dialogArgs) { try { // Pop stack const stack = this.getStack(context); if (stack.length > 0) { stack.pop(); } // Start replacement dialog return this.begin(context, dialogId, dialogArgs); } catch (err) { return Promise.reject(err); } } } exports.DialogSet = DialogSet; function getConversationState(context) { if (!context.state.conversation) { throw new Error(`DialogSet: No conversation state found. Please add a BotStateManager instance to your bots middleware stack.`); } return context.state.conversation; } //# sourceMappingURL=dialogSet.js.map