UNPKG

type2docfx

Version:

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

123 lines (114 loc) 5 kB
/** * @module botbuilder-dialogs */ /** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ import { Promiseable, BotService } from 'botbuilder'; import { Dialog, DialogInstance } from './dialog'; import { DialogSet } from './dialogSet'; import { Context } from 'vm'; /** * Function signature of a waterfall step. * * **Example usage:** * * ```JavaScript * dialogs.add('addAlarm', [ * function (context, alarm, next) { * dialogs.getInstance(context).state = Object.assign({}, alarm); * if (!alarm.title) { * return dialogs.prompt(context, 'titlePrompt', `What would you like to call your alarm?`); * } else { * return next(alarm.title); * } * }, * function (context, title, next) { * const alarm = dialogs.getInstance(context).state; * alarm.title = title; * if (!alarm.time) { * return dialogs.prompt(context, 'timePrompt', `What time would you like to set it for?`); * } else { * return next(alarm.time); * } * }, * function (context, time) { * const alarm = dialogs.getInstance(context).state; * alarm.time = time; * * // ... set alarm ... * * context.reply(`Alarm set.`); * return dialogs.end(context); * } * ]); * ``` * @param WaterfallStep.context The dialog context for the current turn of conversation. * @param WaterfallStep.args Argument(s) passed into the dialog for the first step and then the results from calling a prompt or other dialog for subsequent steps. * @param WaterfallStep.next Function passed into the step to let you manually skip to the next step in the waterfall. */ export type WaterfallStep = (context: BotContext, args?: any, next?: SkipStepFunction) => Promiseable<void>; /** * When called, control will skip to the next waterfall step. * @param SkipStepFunction.args (Optional) additional argument(s) to pass into the next step. */ export type SkipStepFunction = (args?: any) => Promise<void>; /** * Dialog optimized for prompting a user with a series of questions. Waterfalls accept a stack of * functions which will be executed in sequence. Each waterfall step can ask a question of the user * by calling either a prompt or another dialog. When the called dialog completes control will be * returned to the next step of the waterfall and any input collected by the prompt or other dialog * will be passed to the step as an argument. * * When a step is executed it should call either `context.begin()`, `context.end()`, * `context.replace()`, `context.cancelDialog()`, or a prompt. Failing to do so will result * in the dialog automatically ending the next time the user replies. * * Similarly, calling a dialog/prompt from within the last step of the waterfall will result in * the waterfall automatically ending once the dialog/prompt completes. This is often desired * though as the result from tha called dialog/prompt will be passed to the waterfalls parent * dialog. */ export class Waterfall implements Dialog { private readonly steps: WaterfallStep[]; /** * Creates a new waterfall dialog containing the given array of steps. * @param steps Array of waterfall steps. */ constructor(steps: WaterfallStep[]) { this.steps = (steps || []).slice(0); } public begin(context: BotContext, dialogs: DialogSet, args?: any): Promiseable<void> { const instance = dialogs.getInstance(context) as WaterfallInstance<any>; instance.step = 0; return this.runStep(context, dialogs, args); } public resume(context: BotContext, dialogs: DialogSet, result?: any): Promiseable<void> { const instance = dialogs.getInstance(context) as WaterfallInstance<any>; instance.step += 1 return this.runStep(context, dialogs, result); } private runStep(context: BotContext, dialogs: DialogSet, result?: any): Promise<void> { try { const instance = dialogs.getInstance(context) as WaterfallInstance<any>; const step = instance.step; if (step >= 0 && step < this.steps.length) { // Execute step return Promise.resolve(this.steps[step](context, result, (r?: any) => { // Skip to next step instance.step += 1; return this.runStep(context, r); })); } else { // End of waterfall so just return to parent return dialogs.end(context); } } catch (err) { return Promise.reject(err); } } } interface WaterfallInstance<T extends Object> extends DialogInstance<T> { step: number; }